I'm drawing a blank on trying to come up with a simple square grid lookup in python and hope someone can give me some pointers here. Let's say I have a 5x5 grid, starting from the center (3,3), I'd like the lookup to step up the radius outputting the peripheral coordinates like this:
Radius Output
0 [[3,3]]
1 [[2,2], [2,3], [2,4], [3,2], [3,4], [4,2], [4,3], [4,4]]
2 [[1,1], [1,2], [1,3], [1,4], [1,5], [2,1], [2,5], [3,1],
[3,5], [4,1], [4,5], [1,1], [1,2], [1,3], [1,4], [1,5]]
Any pointers will be greatly appreciated!
UPDATE: The code I have at the moment is:
center_coordinate = [3, 3]
completed_locations = [center_coordinate]
radius = 0
max_radius = 3
while radius != max_radius:
x_grid = [x for x in range(center_coordinate[0] - radius, center_coordinate[0] + radius + 1)]
y_grid = [y for y in range(center_coordinate[0] - radius, center_coordinate[0] + radius + 1)]
locations = []
for x in x_grid:
for y in y_grid:
if [x, y] not in completed_locations:
locations.append([x, y])
completed_locations.append([x, y])
radius += 1
print(radius, locations)
While this does do the job, I am looking for a solution that wouldn't require me to cross check each location as it iterates through.. the actual grid size i'll be working against is 750x750 and this particular module will be called on regularly.
Thanks for the pointer #think-maths. I've adapted my code an appreciate the significant boost to performance. I've included both the codes here as reference for anyone doing something similar (like iterating over a game's tile map ;) ).
def adapted_lookup(center_coordinate, max_radius=50):
# ADAPTED FROM think-maths
center_coordinate = [375, 375]
locations_by_radius = []
radius = 0
while radius != max_radius:
x_grid = [x for x in range(center_coordinate[0] - radius, center_coordinate[0] + radius + 1)]
y_grid = [y for y in range(center_coordinate[0] - radius, center_coordinate[0] + radius + 1)]
locations = []
if len(x_grid) > 1:
for x in x_grid:
locations.append([x, y_grid[0]])
if x == x_grid[0] or x == x_grid[-1]:
for y in range(y_grid[1], y_grid[-1]):
locations.append([x, y])
locations.append([x, y_grid[-1]])
else:
locations.append([x_grid[0], y_grid[0]])
locations_by_radius.append([radius, locations])
radius += 1
def original_lookup(center_coordinate, max_radius=50):
# ORIGINAL CODE
locations_by_radius = []
checked = []
radius = 0
while radius != max_radius:
x_grid = [x for x in range(center_coordinate[0] - radius, center_coordinate[0] + radius + 1)]
y_grid = [y for y in range(center_coordinate[0] - radius, center_coordinate[0] + radius + 1)]
locations = []
for x in x_grid:
for y in y_grid:
if [x, y] not in checked:
locations.append([x, y])
checked.append([x, y])
locations_by_radius.append([radius, locations])
radius += 1
Performance according to timeit for a radius of 40 in a 750x750 grid:
Original Lookup Time: 14.5097
Adapted Lookup Time: 0.0020
For such kind of problem where you traverse through grids to form circle then Midpoint circle algorithm is a possibility
For example to demonstrate you can use something like this according to your need to implement your requirement
def midPointCircleDraw(x_centre, y_centre, r):
x = r
y = 0
print("(", x + x_centre, ", ",
y + y_centre, ")",
sep = "", end = "")
if (r > 0) :
print("(", x + x_centre, ", ",
-y + y_centre, ")",
sep = "", end = "")
print("(", y + x_centre, ", ",
x + y_centre, ")",
sep = "", end = "")
print("(", -y + x_centre, ", ",
x + y_centre, ")", sep = "")
P = 1 - r
while x > y:
y += 1
if P <= 0:
P = P + 2 * y + 1
else:
x -= 1
P = P + 2 * y - 2 * x + 1
if (x < y):
break
print("(", x + x_centre, ", ", y + y_centre,
")", sep = "", end = "")
print("(", -x + x_centre, ", ", y + y_centre,
")", sep = "", end = "")
print("(", x + x_centre, ", ", -y + y_centre,
")", sep = "", end = "")
print("(", -x + x_centre, ", ", -y + y_centre,
")", sep = "")
if x != y:
print("(", y + x_centre, ", ", x + y_centre,
")", sep = "", end = "")
print("(", -y + x_centre, ", ", x + y_centre,
")", sep = "", end = "")
print("(", y + x_centre, ", ", -x + y_centre,
")", sep = "", end = "")
print("(", -y + x_centre, ", ", -x + y_centre,
")", sep = "")
Related
In my show() function I can't get the correct amount of recursions and boxes showing. It only goes 1 level deep then stops. Any idea on how to fix it? I'll post all my code to give you some background. When it runs it won't continue to show other boxes that don't have bombs around them or numbered boxes. Not sure what is going wrong as I believe the code is correct but I didn't know how to debug the recursion function. I thought since it could be because being called only once in another function it might limit the recursion. But that does not make sense. I want to get this working to see if it would be possible to run a CSP type algorithm against it. Thanks for the help.
import pygame as pg
import random
pg.init()
HEIGHT, WIDTH = 400, 400
gameloop = True
TILESIZE = 25
class Tile:
def __init__(self, pos):
self.pos = pos
self.bomb = False
self.number = 0
self.show = False
def printAttr(self):
print(self.bomb, self.pos, self.number)
def create_bomb(diction):
b = []
for i in range(1,41):
x = random.randint(0, 15)
y = random.randint(0, 15)
while (x,y) in b:
x = random.randint(0, 15)
y = random.randint(0, 15)
b.append((x,y))
print(len(b))
for item in b:
diction[item].bomb = True
if not diction[item].bomb:
neighbors = [
(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1), (x + 1, y + 1),
(x + 1, y - 1), (x - 1, y + 1), (x - 1, y - 1)
]
neighbors = [neighbor for neighbor in neighbors if validate_cell(neighbor)]
for q in neighbors:
if not diction[q].bomb:
diction[q].number += 1
else:
continue
def validate_cell(neighbor):
if neighbor[0] < 0 or neighbor[1] < 0:
return False
elif neighbor[0] >= 16 or neighbor[1] >= 16:
return False
else:
return True
def create_number(pos, diction):
if not diction[pos].bomb:
neighbors = [
(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1), (x + 1, y + 1),
(x + 1, y - 1), (x - 1, y + 1), (x - 1, y - 1)
]
neighbors = [neighbor for neighbor in neighbors if validate_cell(neighbor)]
count = 0
for item in neighbors:
if diction[item].bomb:
count += 1
else:
continue
if count >= 0:
diction[pos].number = count
def create_board_surf(dis, diction): #creating boaurd
for x in range(16):
for y in range(16):
if diction[(x,y)].show == True:
rect = pg.Rect(x * TILESIZE, y * TILESIZE, TILESIZE, TILESIZE)
pg.draw.rect(dis, pg.Color("grey"), rect, 5)
if diction[(x,y)].number > 0:
rect = pg.Rect(x * TILESIZE+7, y * TILESIZE-3, TILESIZE, TILESIZE)
font = pg.font.SysFont("timesnewroman", 25)
num = diction[(x,y)].number
text = font.render(str(num), False, pg.Color("black"))
dis.blit(text, rect)
else:
rect = pg.Rect(x * TILESIZE, y * TILESIZE, TILESIZE, TILESIZE)
pg.draw.rect(dis, pg.Color("grey"), rect, 2)
# if diction[(x,y)].bomb:
# rect = pg.Rect(x * TILESIZE, y * TILESIZE, TILESIZE, TILESIZE)
# font = pg.font.SysFont("timesnewroman", 25)
# text = font.render("B", False, pg.Color("black"))
# dis.blit(text, rect)
def chosen(pos):
if diction[pos].bomb == True:
diction[pos].show = True
gameloop = False
return gameloop
else:
show(pos)
gameloop = True
return gameloop
def show(pos):
if diction[pos].number == 0 and not diction[pos].show and not diction[pos].bomb:
diction[pos].show = True
neighbors = [
(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1), (x + 1, y + 1),
(x + 1, y - 1), (x - 1, y + 1), (x - 1, y - 1)
]
neighbor1= [neighbor for neighbor in neighbors if validate_cell(neighbor)]
for item in neighbor1:
show(item)
return
if diction[pos].number > 0:
diction[pos].show = True
return
diction = {}
for x in range(16):
for y in range(16):
diction[(x, y)] = Tile([x, y])
create_bomb(diction)
for x in range(16):
for y in range(16):
create_number((x,y), diction)
dis = pg.display.set_mode((HEIGHT, WIDTH))
pg.display.update()
while gameloop:
for event in pg.event.get():
if event.type == pg.QUIT:
gameloop = False
elif event.type == pg.MOUSEBUTTONDOWN:
x, y = [int(v // TILESIZE) for v in pos]
gameloop = chosen((x,y))
pos = pg.Vector2(pg.mouse.get_pos())
dis.fill(pg.Color("white"))
create_board_surf(dis,diction)
pg.display.flip()
Your show-method doesnt know the (updated) value of the variables x and y, so it sets them to the value they had during the first call to show (note that it is only because they get defined as global variables that these initial values of x and y are visible throughout your call-stack - had your main game-loop been in a separate method you would probably have been warned that they were not initialized). Modify your show method as follows
def show(pos):
if diction[pos].number == 0 and not diction[pos].show and not diction[pos].bomb:
diction[pos].show = True
x=pos[0]
y=pos[1]
neighbors = [
(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1), (x + 1, y + 1),
(x + 1, y - 1), (x - 1, y + 1), (x - 1, y - 1)
]
neighbor1= [neighbor for neighbor in neighbors if validate_cell(neighbor)]
for item in neighbor1:
show(item)
return
if diction[pos].number > 0:
diction[pos].show = True
return
and I would expect your program to work.
I have written two algorithms for creating unique mazes, one of them using depth-first-search (DFS) and the other using Kruskal's. The DFS algorithm performs as expected, however Kruskal's algorithm runs marginally slower than DFS and I do not know why.
I had written Kruskal's algorithm in Python.
I suspect the random.choice() function seems to be the underlying problem. The difference in runtime becomes noticeable when (r, c) > 30.
Here is the code for Kruskal's algorithm:
# Create a list of all possible edges
def create_edges(r, c):
edges = []
for y in range(r):
for x in range(c):
i = (y, x)
for d in ((0, 1), (0, -1), (1, 0), (-1, 0)):
p = tuple(map(sum, zip(d, i)))
py = p[0]
px = p[1]
if px in range(c) and py in range(r):
edges.append([i, p])
return edges
def kruskal(r, c, sz):
path = []
# Create a list of parent root nodes
roots = {(y, x) : [(y, x)] for y in range(r) for x in range(c)}
edges = create_edges(r, c)
while edges:
# Choose a random edge
edge = random.choice(edges)
parent = edge[0]
child = edge[1]
parent_set = get_set(roots, parent)
child_set = get_set(roots, child)
# Check if the parent / child are already in the same set
if parent_set == child_set:
rev_edge = edge.reverse()
if rev_edge in edges:
edges.remove(rev_edge)
edges.remove(edge)
continue
roots[parent_set] += roots[child_set]
roots.pop(child_set)
path.extend((parent, child))
rev_edge = edge.reverse()
if rev_edge in edges:
edges.remove(rev_edge)
edges.remove(edge)
return path
def get_set(roots, member):
s = None
for parent, children in roots.items():
if member in children:
s = parent
return s
def create_maze(t, r, c, sz):
maze = [['|_' for _ in range(c)] for _ in range(r)]
for cell in maze: cell.append('| ')
wd = {'DOWN' : ( 1, 0),
'UP' : (-1, 0),
'LEFT' : ( 0, -1),
'RIGHT': ( 0, 1)}
for n in range(len(t) - 1):
a = n
b = n + 1
p1 = t[a]
p2 = t[b]
ay, ax = p1[0], p1[1]
by, bx = p2[0], p2[1]
w = tuple(numpy.array(p2) - numpy.array(p1))
if w in wd.values():
k = list(wd.keys())[list(wd.values()).index(w)]
if k == 'DOWN': maze[ay][ax] = maze[ay][ax].replace('_', ' ')
if k == 'UP': maze[by][bx] = maze[by][bx].replace('_', ' ')
if k == 'LEFT': maze[ay][ax] = maze[ay][ax].replace('|', ' ')
if k == 'RIGHT': maze[by][bx] = maze[by][bx].replace('|', ' ')
return maze
def print_maze(maze, r, c, delay = 0):
s, l = min((r, c)), max((r, c))
a = 1 / (4 * r * c)
e = (1 / (s * l)) ** 2
delay = (a * 2.718 ** (-1 * e)) ** 0.5
time.sleep(delay)
print(' _' * c)
for iy in range(r):
for ix in range(c + 1):
print(maze[iy][ix], end = '')
print('')
print('')
def main():
r = 30
c = 30
sz = r * c
path = kruskal(r, c, sz)
maze = create_maze(path, r, c, sz)
print_maze(maze, r, c)
if __name__ == "__main__":
main()
Trying to write a simple python program to determine if two points (x, y) input by a user fall within a rectangle centered on the (0,0) axis with a width of 10 and height of 5.
Here is where I am.
x = eval(input("Enter the x point : "))
y = eval(input("Enter the y point : "))
if x <= 10.0 / 2:
if y <= 5.0 / 2:
print("Point (" + str(x) + ", " + str(y) + ") is in the rectangle")
else:
print("Point (" + str(x) + ", " + str(y) + ") is not in the rectangle")
This wont work on the negative side. There is a math function I am needing, just can't figure out which one.
I have added a distance = math.sqrt (( x * x ) + ( y * y )) and changed the ifs to distance instead of x and y. I am just so confused.
WIDTH = 10
HEIGHT = 5
X_CENTER = 0
Y_CENTER = 0
x_str = input("Enter the x point: ")
y_str = input("Enter the y point: ")
x = float(x_str)
y = float(y_str)
is_in = True
if not (X_CENTER - WIDTH/2 <= x <= X_CENTER + WIDTH/2):
is_in = False
if not (Y_CENTER - HEIGHT/2 <= y <= Y_CENTER + HEIGHT/2):
is_in = False
if is_in:
statement = "is"
else:
statement = "is not"
print("Point (%s, %s) %s in the rectangle." % (x_str, y_str, statement))
def summation(calc_termo, linf, prox, lsup):
soma = 0
while linf <= lsup:
soma = soma + calc_termo(linf)
linf = prox(linf)
return soma
summation(lambda x: summation(lambda x: x, 1, lambda x: x + 1, x),1, lambda x: x + 1, 5)
I'm having trouble to understand how this code works. I got this as an exercise from my university and I'm having some trouble understanding the code.
It seems to be the sum of the numbers between 1 to 5, but can't understand what summation(lambda x: x, 1, lambda x: x + 1, x) does.
I'd start by taking those arguments apart:
lambda x: summation(lambda x: x, 1, lambda x: x + 1, x)
Substitute those variables back into the the original functions and simplify it:
def inner_function(x):
soma = 0
linf = 1
while linf <= x:
soma += linf + 1
linf += 1
return soma
Simplify that a little more:
def inner_function(x):
soma = 0
for linf in range(1, x + 1):
soma += linf
return soma
And a little more:
inner_function = lambda x: sum(range(1, x + 1))
And some more:
inner_function = lambda x: x * (x + 1) / 2
Now your original function becomes:
def summation(calc_termo, linf, prox, lsup):
soma = 0
while linf <= lsup:
soma = soma + calc_termo(linf)
linf = prox(linf)
return soma
summation(inner_function, 1, lambda x: x + 1, 5)
Or:
def summation(linf, prox, lsup):
soma = 0
while linf <= lsup:
soma = soma + linf * (linf + 1) / 2
linf = prox(linf)
return soma
summation(1, lambda x: x + 1, 5)
You can take it from there. I got:
summation = lambda: sum(n * (n + 1) / 2 for n in range(6))
Which is equal to:
sum(sum(range(n + 1)) for n in range(6))
The last line that you had trouble with could better be stated as:
summation(lambda x: summation(lambda y: y, 1, lambda z: z + 1, x),1, lambda w: w + 1, 5)
The lambdas don't all interfere with each other, if that's what you were confused about.
I need help in the following: I have a data file (columns separated by "\t" tabular) like this data.dat
# y1 y2 y3 y4
17.1685 21.6875 20.2393 26.3158
These are x values of 4 points for a linear fit. The four y values are constant: 0, 200, 400, 600.
I can create a linear fit of the point pairs (x,y): (x1,y1)=(17.1685,0), (x2,y2)=(21.6875,200), (x3,y3)=(20.2393,400), (x4,y4)=(26.3158,600).
Now I would like to make a linear fit on three of these point paris, (x1,y1), (x2,y2), (x3,y3) and (x2,y2), (x3,y3), (x4,y4) and (x1,y1), (x3,y3), (x4,y4) and (x1,y1), (x2,y2), (x4,y4).
If I have these three of points with a linear fit I would like to know the value of the x value of the extrapolated point being out of these three fitted points.
I have so far this awk code:
#!/usr/bin/awk -f
BEGIN{
z[1] = 0;
z[2] = 200;
z[3] = 400;
z[4] = 600;
}
{
split($0,str,"\t");
n = 0.0;
for(i=1; i<=NF; i++)
{
centr[i] = str[i];
n += 1.0;
# printf("%d\t%f\t%.1f\t",i,centr[i],z[i]);
}
# print "";
if (n > 2)
{
lsq(n,z,centr);
}
}
function lsq(n,x,y)
{
sx = 0.0
sy = 0.0
sxx = 0.0
syy = 0.0
sxy = 0.0
eps = 0.0
for (i=1;i<=n;i++)
{
sx += x[i]
sy += y[i]
sxx += x[i]*x[i]
sxy += x[i]*y[i]
syy += y[i]*y[i]
}
if ( (n==0) || ((n*sxx-sx*sx)==0) )
{
next;
}
# print "number of data points = " n;
a = (sxx*sy-sxy*sx)/(n*sxx-sx*sx)
b = (n*sxy-sx*sy)/(n*sxx-sx*sx)
for(i=1;i<=n;i++)
{
ycalc[i] = a+b*x[i]
dy[i] = y[i]-ycalc[i]
eps += dy[i]*dy[i]
}
print "# Intercept =\t"a"
print "# Slope =\t"b"
for (i=1;i<=n;i++)
{
printf("%8g %8g %8g \n",x[i],y[i],ycalc[i])
}
} # function lsq()
So,
If we extrapolate to the place of 4th
0 17.1685 <--(x1,y1)
200 21.6875 <--(x2,y2)
400 20.2393 <--(x3,y3)
600 22.7692 <<< (x4 = 600,y1 = 22.7692)
If we extrapolate to the place of 3th
0 17.1685 <--(x1,y1)
200 21.6875 <--(x2,y2)
400 23.6867 <<< (x3 = 400,y3 = 23.6867)
600 26.3158 <--(x4,y4)
0 17.1685
200 19.35266 <<<
400 20.2393
600 26.3158
0 18.1192 <<<
200 21.6875
400 20.2393
600 26.3158
My current output is the following:
$> ./prog.awk data.dat
# Intercept = 17.4537
# Slope = 0.0129968
0 17.1685 17.4537
200 21.6875 20.0531
400 20.2393 22.6525
600 26.3158 25.2518
Assuming the core calculation in the lsq function is OK (it looks about right, but I haven't scrutinized it), then that gives you the slope and intercept for the least sum of squares line of best fit for the input data set (parameters x, y, n). I'm not sure I understand the tail end of the function.
For your 'take three points and calculate the fourth' problem, the simplest way is to generate the 4 subsets (logically, by deleting one point from the set of four on each of four calls), and redo the calculation.
You need to call another function that takes the line data (slope, intercept) from lsq and interpolates (extrapolates) the value at another y value. That's a straight-forward calculation (x = m * y + c), but you need to determine which y value is missing from the set of 3 you pass in.
You could 'optimize' (meaning 'complicate') this scheme by dropping one value at a time from the 'sums of squares' and 'sums' and 'sum of products' values, recalculating the slope, intercept, and then calculating the missing point again.
(I'll also observe that normally it would be the x-coordinates with the fixed values 0, 200, 400, 600 and the y-coordinates would be the values read. However, that's just a matter of orientation, so it is not crucial.)
Here's at least plausibly working code. Since awk automatically splits on white space, there's no need for you to split on tabs specifically; the read loop takes this into account.
The code needs serious refactoring; there is a ton of repetition in it - however, I also have a job that I'm supposed to do.
#!/usr/bin/awk -f
BEGIN{
z[1] = 0;
z[2] = 200;
z[3] = 400;
z[4] = 600;
}
{
for (i = 1; i <= NF; i++)
{
centr[i] = $i
}
if (NF > 2)
{
lsq(NF, z, centr);
}
}
function lsq(n, x, y)
{
if (n == 0) return
sx = 0.0
sy = 0.0
sxx = 0.0
syy = 0.0
sxy = 0.0
for (i = 1; i <= n; i++)
{
print "x[" i "] = " x[i] ", y[" i "] = " y[i]
sx += x[i]
sy += y[i]
sxx += x[i]*x[i]
sxy += x[i]*y[i]
syy += y[i]*y[i]
}
if ((n*sxx - sx*sx) == 0) return
# print "number of data points = " n;
a = (sxx*sy-sxy*sx)/(n*sxx-sx*sx)
b = (n*sxy-sx*sy)/(n*sxx-sx*sx)
for (i = 1; i <= n; i++)
{
ycalc[i] = a+b*x[i]
}
print "# Intercept = " a
print "# Slope = " b
print "Line: x = " a " + " b " * y"
for (i = 1; i <= n; i++)
{
printf("x = %8g, yo = %8g, yc = %8g\n", x[i], y[i], ycalc[i])
}
print ""
print "Different subsets\n"
for (drop = 1; drop <= n; drop++)
{
print "Subset " drop
sx = sy = sxx = sxy = syy = 0
j = 1
for (i = 1; i <= n; i++)
{
if (i == drop) continue
print "x[" j "] = " x[i] ", y[" j "] = " y[i]
sx += x[i]
sy += y[i]
sxx += x[i]*x[i]
sxy += x[i]*y[i]
syy += y[i]*y[i]
j++
}
if (((n-1)*sxx - sx*sx) == 0) continue
a = (sxx*sy-sxy*sx)/((n-1)*sxx-sx*sx)
b = ((n-1)*sxy-sx*sy)/((n-1)*sxx-sx*sx)
print "Line: x = " a " + " b " * y"
xt = x[drop]
yt = a + b * xt;
print "Interpolate: x = " xt ", y = " yt
}
}
Since awk doesn't provide an easy way to pass back multiple values from a function, nor does it provide structures other than arrays (sometimes associative), it is not perhaps the best language for this task. On the other hand, it can be made to do the job. You might be able to bundle the Least Squares calculation in a function that returns an array containing the slope and intercept, and then use that. Your turn to explore options.
Given the script lsq.awk and the input file lsq.data shown, I get the output shown:
$ cat lsq.data
17.1685 21.6875 20.2393 26.3158
$ awk -f lsq.awk lsq.data
x[1] = 0, y[1] = 17.1685
x[2] = 200, y[2] = 21.6875
x[3] = 400, y[3] = 20.2393
x[4] = 600, y[4] = 26.3158
# Intercept = 17.4537
# Slope = 0.0129968
Line: x = 17.4537 + 0.0129968 * y
x = 0, yo = 17.1685, yc = 17.4537
x = 200, yo = 21.6875, yc = 20.0531
x = 400, yo = 20.2393, yc = 22.6525
x = 600, yo = 26.3158, yc = 25.2518
Different subsets
Subset 1
x[1] = 200, y[1] = 21.6875
x[2] = 400, y[2] = 20.2393
x[3] = 600, y[3] = 26.3158
Line: x = 18.1192 + 0.0115708 * y
Interpolate: x = 0, y = 18.1192
Subset 2
x[1] = 0, y[1] = 17.1685
x[2] = 400, y[2] = 20.2393
x[3] = 600, y[3] = 26.3158
Line: x = 16.5198 + 0.0141643 * y
Interpolate: x = 200, y = 19.3526
Subset 3
x[1] = 0, y[1] = 17.1685
x[2] = 200, y[2] = 21.6875
x[3] = 600, y[3] = 26.3158
Line: x = 17.7985 + 0.0147205 * y
Interpolate: x = 400, y = 23.6867
Subset 4
x[1] = 0, y[1] = 17.1685
x[2] = 200, y[2] = 21.6875
x[3] = 400, y[3] = 20.2393
Line: x = 18.163 + 0.007677 * y
Interpolate: x = 600, y = 22.7692
$
Edit: In the previous version of the answer, the subsets were multiplying by n instead of (n-1). The values in the revised output seem to agree with what you expect. The residual issues are presentational, not computational.