Shortest distance for points in a plane

Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
8
down vote
favorite
I was wondering how I can make this code more pythonic. More professonal-looking and more readable. The code runs perfectly fine.
# Uses Python 3
"""
Finds the closest pair of point from a set of points on a plane
by brute-force (O(n^2)) and divide-and-conquer algorithms (O(nlog(n))).
Input: x,y coordinates (float)
Output: minimum distance (float)& closest pair (complex number)
@ Author: RA
"""
import sys
# Brute force algorithm.
def brute_force(xpoints): # px will be passed to the function
n = len(xpoints)
if n < 2:
return float('inf'), (None, None)
else:
sep = float('inf') # set the initial minimum to infinity
pair = ()
for i in range(n - 1):
for j in range(i + 1, n):
if abs(xpoints[i] - xpoints[j]) < sep:
sep = abs(xpoints[i] - xpoints[j])
pair = (xpoints[i], xpoints[j])
return sep, pair
# Divide and Conquer
def divide_n_conquer(xpoints, ypoints):
n = len(xpoints)
if n <= 3:
return brute_force(xpoints)
xmedian = int(n / 2)
yl, yr = ,
for p in ypoints:
if p.real < xpoints[xmedian].real:
yl.append(p)
else:
yr.append(p)
(l_sep, l_pair) = divide_n_conquer(xpoints[:xmedian], yl)
(r_sep, r_pair) = divide_n_conquer(xpoints[xmedian:], yr)
(sep, pair) = (l_sep, l_pair) if l_sep < r_sep else (r_sep, r_pair)
sep_strip, pair_strip = split(xpoints, ypoints, sep)
if sep_strip < sep:
sep = sep_strip
pair = pair_strip
return sep, pair
def split(xpoints, ypoints, sep):
xdivider = xpoints[int(len(xpoints)/2)].real
ystrip = [item for item in ypoints if
abs(item.real - xdivider).real < sep]
ns = len(ystrip) # Number of points in the strip
sep = float('inf')
pair = ()
if ns > 1:
for i in range(ns - 1):
for j in range(i + 1, min(i + 8, ns)):
if abs(ystrip[i] - ystrip[j]) < sep:
sep, pair = abs(ystrip[i] - ystrip[j]), (ystrip[i], ystrip[j])
return sep, pair
if __name__ == '__main__':
_input = sys.stdin.read()
data = list(map(int, _input.split()))
n = data[0]
x = data[1::2]
y = data[2::2]
p = [complex(x, y) for x, y in zip(x, y)]
px = sorted(p, key=lambda p: p.real) # points sorted by x
py = sorted(p, key=lambda p: p.imag) # points sorted by y
print("0:.9f".format(divide_n_conquer(px, py)[0]))
python algorithm python-3.x sorting divide-and-conquer
add a comment |Â
up vote
8
down vote
favorite
I was wondering how I can make this code more pythonic. More professonal-looking and more readable. The code runs perfectly fine.
# Uses Python 3
"""
Finds the closest pair of point from a set of points on a plane
by brute-force (O(n^2)) and divide-and-conquer algorithms (O(nlog(n))).
Input: x,y coordinates (float)
Output: minimum distance (float)& closest pair (complex number)
@ Author: RA
"""
import sys
# Brute force algorithm.
def brute_force(xpoints): # px will be passed to the function
n = len(xpoints)
if n < 2:
return float('inf'), (None, None)
else:
sep = float('inf') # set the initial minimum to infinity
pair = ()
for i in range(n - 1):
for j in range(i + 1, n):
if abs(xpoints[i] - xpoints[j]) < sep:
sep = abs(xpoints[i] - xpoints[j])
pair = (xpoints[i], xpoints[j])
return sep, pair
# Divide and Conquer
def divide_n_conquer(xpoints, ypoints):
n = len(xpoints)
if n <= 3:
return brute_force(xpoints)
xmedian = int(n / 2)
yl, yr = ,
for p in ypoints:
if p.real < xpoints[xmedian].real:
yl.append(p)
else:
yr.append(p)
(l_sep, l_pair) = divide_n_conquer(xpoints[:xmedian], yl)
(r_sep, r_pair) = divide_n_conquer(xpoints[xmedian:], yr)
(sep, pair) = (l_sep, l_pair) if l_sep < r_sep else (r_sep, r_pair)
sep_strip, pair_strip = split(xpoints, ypoints, sep)
if sep_strip < sep:
sep = sep_strip
pair = pair_strip
return sep, pair
def split(xpoints, ypoints, sep):
xdivider = xpoints[int(len(xpoints)/2)].real
ystrip = [item for item in ypoints if
abs(item.real - xdivider).real < sep]
ns = len(ystrip) # Number of points in the strip
sep = float('inf')
pair = ()
if ns > 1:
for i in range(ns - 1):
for j in range(i + 1, min(i + 8, ns)):
if abs(ystrip[i] - ystrip[j]) < sep:
sep, pair = abs(ystrip[i] - ystrip[j]), (ystrip[i], ystrip[j])
return sep, pair
if __name__ == '__main__':
_input = sys.stdin.read()
data = list(map(int, _input.split()))
n = data[0]
x = data[1::2]
y = data[2::2]
p = [complex(x, y) for x, y in zip(x, y)]
px = sorted(p, key=lambda p: p.real) # points sorted by x
py = sorted(p, key=lambda p: p.imag) # points sorted by y
print("0:.9f".format(divide_n_conquer(px, py)[0]))
python algorithm python-3.x sorting divide-and-conquer
add a comment |Â
up vote
8
down vote
favorite
up vote
8
down vote
favorite
I was wondering how I can make this code more pythonic. More professonal-looking and more readable. The code runs perfectly fine.
# Uses Python 3
"""
Finds the closest pair of point from a set of points on a plane
by brute-force (O(n^2)) and divide-and-conquer algorithms (O(nlog(n))).
Input: x,y coordinates (float)
Output: minimum distance (float)& closest pair (complex number)
@ Author: RA
"""
import sys
# Brute force algorithm.
def brute_force(xpoints): # px will be passed to the function
n = len(xpoints)
if n < 2:
return float('inf'), (None, None)
else:
sep = float('inf') # set the initial minimum to infinity
pair = ()
for i in range(n - 1):
for j in range(i + 1, n):
if abs(xpoints[i] - xpoints[j]) < sep:
sep = abs(xpoints[i] - xpoints[j])
pair = (xpoints[i], xpoints[j])
return sep, pair
# Divide and Conquer
def divide_n_conquer(xpoints, ypoints):
n = len(xpoints)
if n <= 3:
return brute_force(xpoints)
xmedian = int(n / 2)
yl, yr = ,
for p in ypoints:
if p.real < xpoints[xmedian].real:
yl.append(p)
else:
yr.append(p)
(l_sep, l_pair) = divide_n_conquer(xpoints[:xmedian], yl)
(r_sep, r_pair) = divide_n_conquer(xpoints[xmedian:], yr)
(sep, pair) = (l_sep, l_pair) if l_sep < r_sep else (r_sep, r_pair)
sep_strip, pair_strip = split(xpoints, ypoints, sep)
if sep_strip < sep:
sep = sep_strip
pair = pair_strip
return sep, pair
def split(xpoints, ypoints, sep):
xdivider = xpoints[int(len(xpoints)/2)].real
ystrip = [item for item in ypoints if
abs(item.real - xdivider).real < sep]
ns = len(ystrip) # Number of points in the strip
sep = float('inf')
pair = ()
if ns > 1:
for i in range(ns - 1):
for j in range(i + 1, min(i + 8, ns)):
if abs(ystrip[i] - ystrip[j]) < sep:
sep, pair = abs(ystrip[i] - ystrip[j]), (ystrip[i], ystrip[j])
return sep, pair
if __name__ == '__main__':
_input = sys.stdin.read()
data = list(map(int, _input.split()))
n = data[0]
x = data[1::2]
y = data[2::2]
p = [complex(x, y) for x, y in zip(x, y)]
px = sorted(p, key=lambda p: p.real) # points sorted by x
py = sorted(p, key=lambda p: p.imag) # points sorted by y
print("0:.9f".format(divide_n_conquer(px, py)[0]))
python algorithm python-3.x sorting divide-and-conquer
I was wondering how I can make this code more pythonic. More professonal-looking and more readable. The code runs perfectly fine.
# Uses Python 3
"""
Finds the closest pair of point from a set of points on a plane
by brute-force (O(n^2)) and divide-and-conquer algorithms (O(nlog(n))).
Input: x,y coordinates (float)
Output: minimum distance (float)& closest pair (complex number)
@ Author: RA
"""
import sys
# Brute force algorithm.
def brute_force(xpoints): # px will be passed to the function
n = len(xpoints)
if n < 2:
return float('inf'), (None, None)
else:
sep = float('inf') # set the initial minimum to infinity
pair = ()
for i in range(n - 1):
for j in range(i + 1, n):
if abs(xpoints[i] - xpoints[j]) < sep:
sep = abs(xpoints[i] - xpoints[j])
pair = (xpoints[i], xpoints[j])
return sep, pair
# Divide and Conquer
def divide_n_conquer(xpoints, ypoints):
n = len(xpoints)
if n <= 3:
return brute_force(xpoints)
xmedian = int(n / 2)
yl, yr = ,
for p in ypoints:
if p.real < xpoints[xmedian].real:
yl.append(p)
else:
yr.append(p)
(l_sep, l_pair) = divide_n_conquer(xpoints[:xmedian], yl)
(r_sep, r_pair) = divide_n_conquer(xpoints[xmedian:], yr)
(sep, pair) = (l_sep, l_pair) if l_sep < r_sep else (r_sep, r_pair)
sep_strip, pair_strip = split(xpoints, ypoints, sep)
if sep_strip < sep:
sep = sep_strip
pair = pair_strip
return sep, pair
def split(xpoints, ypoints, sep):
xdivider = xpoints[int(len(xpoints)/2)].real
ystrip = [item for item in ypoints if
abs(item.real - xdivider).real < sep]
ns = len(ystrip) # Number of points in the strip
sep = float('inf')
pair = ()
if ns > 1:
for i in range(ns - 1):
for j in range(i + 1, min(i + 8, ns)):
if abs(ystrip[i] - ystrip[j]) < sep:
sep, pair = abs(ystrip[i] - ystrip[j]), (ystrip[i], ystrip[j])
return sep, pair
if __name__ == '__main__':
_input = sys.stdin.read()
data = list(map(int, _input.split()))
n = data[0]
x = data[1::2]
y = data[2::2]
p = [complex(x, y) for x, y in zip(x, y)]
px = sorted(p, key=lambda p: p.real) # points sorted by x
py = sorted(p, key=lambda p: p.imag) # points sorted by y
print("0:.9f".format(divide_n_conquer(px, py)[0]))
python algorithm python-3.x sorting divide-and-conquer
edited Apr 7 at 4:14
Phrancis
14.6k644137
14.6k644137
asked Apr 7 at 3:48
Reza Afra
462
462
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
6
down vote
Just reviewing brute_force.
There's no docstring.
There's no need to write comments if they just repeat what it says in the code:
sep = float('inf') # set the initial minimum to infinityUse comments to explain things that are hard to deduce from reading the code.
The special case for
n < 2is unnecessary. Ifnis less than 2, then the loop overiwill be empty and no pairs will be tested.There are some superfluous parentheses. In Python the comma operator has higher precedence than assignment, and so, instead of:
pair = (xpoints[i], xpoints[j])you can write:
pair = xpoints[i], xpoints[j]The expression
abs(xpoints[i] - xpoints[j])gets computed twice in some cases: this could be avoided by storing the result in a local variable.When looping over the distinct pairs of a sequence, use
itertools.combinations, like this:from itertools import combinations
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
sep = float('inf')
pair = None, None
for p, q in combinations(points, 2):
pq_sep = abs(p - q)
if pq_sep < sep:
sep = pq_sep
pair = p, q
return sep, pairThis could be turned into a single expression using
minandoperator.itemgetter:from itertools import combinations
from operator import itemgetter
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
return min(((abs(p - q), (p, q)) for p, q in combinations(points, 2)),
key=itemgetter(0), default=(float('inf'), (None, None)))(This needs to be Python 3.4 or later since it uses the
defaultkeyword argument.)Not everyone finds this style of programming readable, so it would be totally reasonable to stop with the version in ç6 above and not try to squash everything into a single expression.
2
Nice answer. The last example though looks a bit...too much when it comes to "more readable" ^_^
â ÃÂïàú
Apr 7 at 11:55
That's really nice code. Thanks.
â Reza Afra
Apr 7 at 12:59
add a comment |Â
up vote
1
down vote
Three comments on the general style of your code, skipping what's already said in the other answer.
1. Express co-ordinate ideas in similar form.
For an external user, both functions brute_force and divide_n_conquer are identical. There is no reason for these functions to have different signatures.
Suggestion: arguments for brute_force and for divide_n_conquer should be identical.
Variable naming:
why l_sep, l_pair and yl (not l_y)?
2. Use definite, specific, concrete language.
Variable names such as l_sep, l_pair, sep, ns, are not clear without context. If you cannot come up with better names, then document them explicitly. The less general, the better.
3. Do not break a sentence into two.
The function split (seems) useless outside of divide_n_conquer. Ideally split would belong inside of the body of divide_n_conquer. This cannot happen without refactoring the code because of the recursive calls, i.e., split would be redefined at every function call. A pythonic solution to this problem is to mark the function split as a helper function, by renaming it _split. See more info here.
Alternatively, split can be defined inside of divide_n_conquer, provided you define another helper function divide_n_conquer_recurse, for example.
The function would then look something like:
def divide_n_conquer(xpoints): # Same signature as brute_force. See 1.
def split(xpoints, ypoints, sep):
pass
def divide_n_conquer_recurse(...conditions):
if base_condition: # n <=3 ?
return brute_force(xpoints)
else:
if some_condition: # l_sep < r_sep ?
updated_conditions = split(...)
return divide_n_conquer_recurse(updated_conditions)
else:
other_conditions = split(...)
return divide_n_conquer_recurse(other_conditions)
# parse xpoints into xpoints and ypoints.
...
return divide_n_conquer_recurse(...initial_conditions)
Small disclaimer:
Paragraph names inspired by The Elements Of Style.
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
6
down vote
Just reviewing brute_force.
There's no docstring.
There's no need to write comments if they just repeat what it says in the code:
sep = float('inf') # set the initial minimum to infinityUse comments to explain things that are hard to deduce from reading the code.
The special case for
n < 2is unnecessary. Ifnis less than 2, then the loop overiwill be empty and no pairs will be tested.There are some superfluous parentheses. In Python the comma operator has higher precedence than assignment, and so, instead of:
pair = (xpoints[i], xpoints[j])you can write:
pair = xpoints[i], xpoints[j]The expression
abs(xpoints[i] - xpoints[j])gets computed twice in some cases: this could be avoided by storing the result in a local variable.When looping over the distinct pairs of a sequence, use
itertools.combinations, like this:from itertools import combinations
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
sep = float('inf')
pair = None, None
for p, q in combinations(points, 2):
pq_sep = abs(p - q)
if pq_sep < sep:
sep = pq_sep
pair = p, q
return sep, pairThis could be turned into a single expression using
minandoperator.itemgetter:from itertools import combinations
from operator import itemgetter
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
return min(((abs(p - q), (p, q)) for p, q in combinations(points, 2)),
key=itemgetter(0), default=(float('inf'), (None, None)))(This needs to be Python 3.4 or later since it uses the
defaultkeyword argument.)Not everyone finds this style of programming readable, so it would be totally reasonable to stop with the version in ç6 above and not try to squash everything into a single expression.
2
Nice answer. The last example though looks a bit...too much when it comes to "more readable" ^_^
â ÃÂïàú
Apr 7 at 11:55
That's really nice code. Thanks.
â Reza Afra
Apr 7 at 12:59
add a comment |Â
up vote
6
down vote
Just reviewing brute_force.
There's no docstring.
There's no need to write comments if they just repeat what it says in the code:
sep = float('inf') # set the initial minimum to infinityUse comments to explain things that are hard to deduce from reading the code.
The special case for
n < 2is unnecessary. Ifnis less than 2, then the loop overiwill be empty and no pairs will be tested.There are some superfluous parentheses. In Python the comma operator has higher precedence than assignment, and so, instead of:
pair = (xpoints[i], xpoints[j])you can write:
pair = xpoints[i], xpoints[j]The expression
abs(xpoints[i] - xpoints[j])gets computed twice in some cases: this could be avoided by storing the result in a local variable.When looping over the distinct pairs of a sequence, use
itertools.combinations, like this:from itertools import combinations
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
sep = float('inf')
pair = None, None
for p, q in combinations(points, 2):
pq_sep = abs(p - q)
if pq_sep < sep:
sep = pq_sep
pair = p, q
return sep, pairThis could be turned into a single expression using
minandoperator.itemgetter:from itertools import combinations
from operator import itemgetter
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
return min(((abs(p - q), (p, q)) for p, q in combinations(points, 2)),
key=itemgetter(0), default=(float('inf'), (None, None)))(This needs to be Python 3.4 or later since it uses the
defaultkeyword argument.)Not everyone finds this style of programming readable, so it would be totally reasonable to stop with the version in ç6 above and not try to squash everything into a single expression.
2
Nice answer. The last example though looks a bit...too much when it comes to "more readable" ^_^
â ÃÂïàú
Apr 7 at 11:55
That's really nice code. Thanks.
â Reza Afra
Apr 7 at 12:59
add a comment |Â
up vote
6
down vote
up vote
6
down vote
Just reviewing brute_force.
There's no docstring.
There's no need to write comments if they just repeat what it says in the code:
sep = float('inf') # set the initial minimum to infinityUse comments to explain things that are hard to deduce from reading the code.
The special case for
n < 2is unnecessary. Ifnis less than 2, then the loop overiwill be empty and no pairs will be tested.There are some superfluous parentheses. In Python the comma operator has higher precedence than assignment, and so, instead of:
pair = (xpoints[i], xpoints[j])you can write:
pair = xpoints[i], xpoints[j]The expression
abs(xpoints[i] - xpoints[j])gets computed twice in some cases: this could be avoided by storing the result in a local variable.When looping over the distinct pairs of a sequence, use
itertools.combinations, like this:from itertools import combinations
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
sep = float('inf')
pair = None, None
for p, q in combinations(points, 2):
pq_sep = abs(p - q)
if pq_sep < sep:
sep = pq_sep
pair = p, q
return sep, pairThis could be turned into a single expression using
minandoperator.itemgetter:from itertools import combinations
from operator import itemgetter
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
return min(((abs(p - q), (p, q)) for p, q in combinations(points, 2)),
key=itemgetter(0), default=(float('inf'), (None, None)))(This needs to be Python 3.4 or later since it uses the
defaultkeyword argument.)Not everyone finds this style of programming readable, so it would be totally reasonable to stop with the version in ç6 above and not try to squash everything into a single expression.
Just reviewing brute_force.
There's no docstring.
There's no need to write comments if they just repeat what it says in the code:
sep = float('inf') # set the initial minimum to infinityUse comments to explain things that are hard to deduce from reading the code.
The special case for
n < 2is unnecessary. Ifnis less than 2, then the loop overiwill be empty and no pairs will be tested.There are some superfluous parentheses. In Python the comma operator has higher precedence than assignment, and so, instead of:
pair = (xpoints[i], xpoints[j])you can write:
pair = xpoints[i], xpoints[j]The expression
abs(xpoints[i] - xpoints[j])gets computed twice in some cases: this could be avoided by storing the result in a local variable.When looping over the distinct pairs of a sequence, use
itertools.combinations, like this:from itertools import combinations
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
sep = float('inf')
pair = None, None
for p, q in combinations(points, 2):
pq_sep = abs(p - q)
if pq_sep < sep:
sep = pq_sep
pair = p, q
return sep, pairThis could be turned into a single expression using
minandoperator.itemgetter:from itertools import combinations
from operator import itemgetter
def brute_force(points):
"""Find the pair (p, q) in the sequence points with the closest
separation. Return the tuple (separation, (p, q)).
"""
return min(((abs(p - q), (p, q)) for p, q in combinations(points, 2)),
key=itemgetter(0), default=(float('inf'), (None, None)))(This needs to be Python 3.4 or later since it uses the
defaultkeyword argument.)Not everyone finds this style of programming readable, so it would be totally reasonable to stop with the version in ç6 above and not try to squash everything into a single expression.
edited Apr 7 at 22:43
answered Apr 7 at 11:35
Gareth Rees
41.1k394166
41.1k394166
2
Nice answer. The last example though looks a bit...too much when it comes to "more readable" ^_^
â ÃÂïàú
Apr 7 at 11:55
That's really nice code. Thanks.
â Reza Afra
Apr 7 at 12:59
add a comment |Â
2
Nice answer. The last example though looks a bit...too much when it comes to "more readable" ^_^
â ÃÂïàú
Apr 7 at 11:55
That's really nice code. Thanks.
â Reza Afra
Apr 7 at 12:59
2
2
Nice answer. The last example though looks a bit...too much when it comes to "more readable" ^_^
â ÃÂïàú
Apr 7 at 11:55
Nice answer. The last example though looks a bit...too much when it comes to "more readable" ^_^
â ÃÂïàú
Apr 7 at 11:55
That's really nice code. Thanks.
â Reza Afra
Apr 7 at 12:59
That's really nice code. Thanks.
â Reza Afra
Apr 7 at 12:59
add a comment |Â
up vote
1
down vote
Three comments on the general style of your code, skipping what's already said in the other answer.
1. Express co-ordinate ideas in similar form.
For an external user, both functions brute_force and divide_n_conquer are identical. There is no reason for these functions to have different signatures.
Suggestion: arguments for brute_force and for divide_n_conquer should be identical.
Variable naming:
why l_sep, l_pair and yl (not l_y)?
2. Use definite, specific, concrete language.
Variable names such as l_sep, l_pair, sep, ns, are not clear without context. If you cannot come up with better names, then document them explicitly. The less general, the better.
3. Do not break a sentence into two.
The function split (seems) useless outside of divide_n_conquer. Ideally split would belong inside of the body of divide_n_conquer. This cannot happen without refactoring the code because of the recursive calls, i.e., split would be redefined at every function call. A pythonic solution to this problem is to mark the function split as a helper function, by renaming it _split. See more info here.
Alternatively, split can be defined inside of divide_n_conquer, provided you define another helper function divide_n_conquer_recurse, for example.
The function would then look something like:
def divide_n_conquer(xpoints): # Same signature as brute_force. See 1.
def split(xpoints, ypoints, sep):
pass
def divide_n_conquer_recurse(...conditions):
if base_condition: # n <=3 ?
return brute_force(xpoints)
else:
if some_condition: # l_sep < r_sep ?
updated_conditions = split(...)
return divide_n_conquer_recurse(updated_conditions)
else:
other_conditions = split(...)
return divide_n_conquer_recurse(other_conditions)
# parse xpoints into xpoints and ypoints.
...
return divide_n_conquer_recurse(...initial_conditions)
Small disclaimer:
Paragraph names inspired by The Elements Of Style.
add a comment |Â
up vote
1
down vote
Three comments on the general style of your code, skipping what's already said in the other answer.
1. Express co-ordinate ideas in similar form.
For an external user, both functions brute_force and divide_n_conquer are identical. There is no reason for these functions to have different signatures.
Suggestion: arguments for brute_force and for divide_n_conquer should be identical.
Variable naming:
why l_sep, l_pair and yl (not l_y)?
2. Use definite, specific, concrete language.
Variable names such as l_sep, l_pair, sep, ns, are not clear without context. If you cannot come up with better names, then document them explicitly. The less general, the better.
3. Do not break a sentence into two.
The function split (seems) useless outside of divide_n_conquer. Ideally split would belong inside of the body of divide_n_conquer. This cannot happen without refactoring the code because of the recursive calls, i.e., split would be redefined at every function call. A pythonic solution to this problem is to mark the function split as a helper function, by renaming it _split. See more info here.
Alternatively, split can be defined inside of divide_n_conquer, provided you define another helper function divide_n_conquer_recurse, for example.
The function would then look something like:
def divide_n_conquer(xpoints): # Same signature as brute_force. See 1.
def split(xpoints, ypoints, sep):
pass
def divide_n_conquer_recurse(...conditions):
if base_condition: # n <=3 ?
return brute_force(xpoints)
else:
if some_condition: # l_sep < r_sep ?
updated_conditions = split(...)
return divide_n_conquer_recurse(updated_conditions)
else:
other_conditions = split(...)
return divide_n_conquer_recurse(other_conditions)
# parse xpoints into xpoints and ypoints.
...
return divide_n_conquer_recurse(...initial_conditions)
Small disclaimer:
Paragraph names inspired by The Elements Of Style.
add a comment |Â
up vote
1
down vote
up vote
1
down vote
Three comments on the general style of your code, skipping what's already said in the other answer.
1. Express co-ordinate ideas in similar form.
For an external user, both functions brute_force and divide_n_conquer are identical. There is no reason for these functions to have different signatures.
Suggestion: arguments for brute_force and for divide_n_conquer should be identical.
Variable naming:
why l_sep, l_pair and yl (not l_y)?
2. Use definite, specific, concrete language.
Variable names such as l_sep, l_pair, sep, ns, are not clear without context. If you cannot come up with better names, then document them explicitly. The less general, the better.
3. Do not break a sentence into two.
The function split (seems) useless outside of divide_n_conquer. Ideally split would belong inside of the body of divide_n_conquer. This cannot happen without refactoring the code because of the recursive calls, i.e., split would be redefined at every function call. A pythonic solution to this problem is to mark the function split as a helper function, by renaming it _split. See more info here.
Alternatively, split can be defined inside of divide_n_conquer, provided you define another helper function divide_n_conquer_recurse, for example.
The function would then look something like:
def divide_n_conquer(xpoints): # Same signature as brute_force. See 1.
def split(xpoints, ypoints, sep):
pass
def divide_n_conquer_recurse(...conditions):
if base_condition: # n <=3 ?
return brute_force(xpoints)
else:
if some_condition: # l_sep < r_sep ?
updated_conditions = split(...)
return divide_n_conquer_recurse(updated_conditions)
else:
other_conditions = split(...)
return divide_n_conquer_recurse(other_conditions)
# parse xpoints into xpoints and ypoints.
...
return divide_n_conquer_recurse(...initial_conditions)
Small disclaimer:
Paragraph names inspired by The Elements Of Style.
Three comments on the general style of your code, skipping what's already said in the other answer.
1. Express co-ordinate ideas in similar form.
For an external user, both functions brute_force and divide_n_conquer are identical. There is no reason for these functions to have different signatures.
Suggestion: arguments for brute_force and for divide_n_conquer should be identical.
Variable naming:
why l_sep, l_pair and yl (not l_y)?
2. Use definite, specific, concrete language.
Variable names such as l_sep, l_pair, sep, ns, are not clear without context. If you cannot come up with better names, then document them explicitly. The less general, the better.
3. Do not break a sentence into two.
The function split (seems) useless outside of divide_n_conquer. Ideally split would belong inside of the body of divide_n_conquer. This cannot happen without refactoring the code because of the recursive calls, i.e., split would be redefined at every function call. A pythonic solution to this problem is to mark the function split as a helper function, by renaming it _split. See more info here.
Alternatively, split can be defined inside of divide_n_conquer, provided you define another helper function divide_n_conquer_recurse, for example.
The function would then look something like:
def divide_n_conquer(xpoints): # Same signature as brute_force. See 1.
def split(xpoints, ypoints, sep):
pass
def divide_n_conquer_recurse(...conditions):
if base_condition: # n <=3 ?
return brute_force(xpoints)
else:
if some_condition: # l_sep < r_sep ?
updated_conditions = split(...)
return divide_n_conquer_recurse(updated_conditions)
else:
other_conditions = split(...)
return divide_n_conquer_recurse(other_conditions)
# parse xpoints into xpoints and ypoints.
...
return divide_n_conquer_recurse(...initial_conditions)
Small disclaimer:
Paragraph names inspired by The Elements Of Style.
answered Apr 9 at 23:18
dangom
1714
1714
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191456%2fshortest-distance-for-points-in-a-plane%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password