Simplify proximity function using fewer ors & ands?
Question:
Both p
and s
are tuples with values like (1,9)
, (4,7)
, (5,6)
, etc.
The function checks if a node is close to another node (exactly one unit away) to find the best path.
def prox(p,s):
if (p[0]==s[0]+1 and p[1]==s[1]) or (p[0]==s[0]-1 and p[1]==s[1]) or (p[1]==s[1]+1 and p[0]==s[0]) or (p[1]==s[1]-1 and p[0]==s[0]) or (p[0]+1==s[0] and p[1]==s[1]) or (p[0]-1==s[0] and p[1]==s[1]) or (p[1]+1==s[1] and p[0]==s[0]) or (p[1]-1==s[1] and p[0]==s[0]):
return True
else:
return False
It works fine but I feel like there’s a better way to write it.
Answers:
Pls check the following code, I checked the conditions carefully so I believe constraint haven’t changed.
First option :
def prox(p,s):
if abs(p[0]-s[0]) <= 1 and abs(p[1]-s[1]) <= 1:
return True
else:
return False
You said you are new to python, so if it might confusing there’s that option as well
Second option :
def prox(p,s):
if (p[0] in [s[0]+1, s[0]-1] and p[1]==s[1]) or (p[1] in [s[1]+1, s[1]-1] and p[0]==s[0]):
return True
else:
return False
def prox(p, s):
return (abs(p[0] - s[0]) + abs(p[1] - s[1]) == 1)
This function checks if two points are neighbors in a 2D grid where movement is only allowed in four cardinal directions (north, south, east, west). The proximity is determined by calculating the Manhattan distance between two points. The Manhattan distance (also known as L1 distance) is the sum of absolute differences of the x and y coordinates of two points. The function returns True if the Manhattan distance between p
and s
is equal to 1 (i.e., adjacent).
Let’s do this a little at a time. You’re new to Python, so if you don’t understand all the tools used here, that’s fine! I’d recommend picking the most concise code that you personally still find readable at this point. I’ve provided links to learn more about the builtins and language constructs used.
First of all, you’re using this classic antipattern:
if boolean_condition:
return True
else:
return False
boolean_condition
is already True
or False
, so anytime you see this structure, you can simplify it to just:
return boolean_condition
That already gets us down to:
def prox(p, s):
return ((p[0]==s[0]+1 and p[1]==s[1]) or
(p[0]==s[0]-1 and p[1]==s[1]) or
(p[1]==s[1]+1 and p[0]==s[0]) or
(p[1]==s[1]-1 and p[0]==s[0]) or
(p[0]+1==s[0] and p[1]==s[1]) or
(p[0]-1==s[0] and p[1]==s[1]) or
(p[1]+1==s[1] and p[0]==s[0]) or
(p[1]-1==s[1] and p[0]==s[0]))
(Broken up onto multiple lines by enclosing in parentheses, to make it more readable)
Now, you want to check if the distance between the two nodes is exactly 1
, correct? So either the x
or y
coordinates need to be one apart, but not both. That means that if you subtract the two x
s and take the absolute value of that difference, then do the same for the y
s, then add the two differences, it should equal 1
.
We could start by writing this as a for
loop with zip
to iterate through both tuples together, adding up the absolute value of differences:
def prox(p, s):
total_difference = 0
for first, second in zip(p, s):
total_difference += abs(first - second)
return total_difference == 1
This can be condensed using Python’s built-in sum
function and a generator expression:
def prox(p, s):
total_difference = sum(abs(first - second) for first, second in zip(p, s))
return total_difference == 1
Or, skipping the intermediate variable:
def prox(p, s):
return sum(abs(first - second) for first, second in zip(p, s)) == 1
Bonus: this same function generalizes to three (or any number of) dimensions. Probably not useful in this case, but neat.
Both p
and s
are tuples with values like (1,9)
, (4,7)
, (5,6)
, etc.
The function checks if a node is close to another node (exactly one unit away) to find the best path.
def prox(p,s):
if (p[0]==s[0]+1 and p[1]==s[1]) or (p[0]==s[0]-1 and p[1]==s[1]) or (p[1]==s[1]+1 and p[0]==s[0]) or (p[1]==s[1]-1 and p[0]==s[0]) or (p[0]+1==s[0] and p[1]==s[1]) or (p[0]-1==s[0] and p[1]==s[1]) or (p[1]+1==s[1] and p[0]==s[0]) or (p[1]-1==s[1] and p[0]==s[0]):
return True
else:
return False
It works fine but I feel like there’s a better way to write it.
Pls check the following code, I checked the conditions carefully so I believe constraint haven’t changed.
First option :
def prox(p,s):
if abs(p[0]-s[0]) <= 1 and abs(p[1]-s[1]) <= 1:
return True
else:
return False
You said you are new to python, so if it might confusing there’s that option as well
Second option :
def prox(p,s):
if (p[0] in [s[0]+1, s[0]-1] and p[1]==s[1]) or (p[1] in [s[1]+1, s[1]-1] and p[0]==s[0]):
return True
else:
return False
def prox(p, s):
return (abs(p[0] - s[0]) + abs(p[1] - s[1]) == 1)
This function checks if two points are neighbors in a 2D grid where movement is only allowed in four cardinal directions (north, south, east, west). The proximity is determined by calculating the Manhattan distance between two points. The Manhattan distance (also known as L1 distance) is the sum of absolute differences of the x and y coordinates of two points. The function returns True if the Manhattan distance between p
and s
is equal to 1 (i.e., adjacent).
Let’s do this a little at a time. You’re new to Python, so if you don’t understand all the tools used here, that’s fine! I’d recommend picking the most concise code that you personally still find readable at this point. I’ve provided links to learn more about the builtins and language constructs used.
First of all, you’re using this classic antipattern:
if boolean_condition:
return True
else:
return False
boolean_condition
is already True
or False
, so anytime you see this structure, you can simplify it to just:
return boolean_condition
That already gets us down to:
def prox(p, s):
return ((p[0]==s[0]+1 and p[1]==s[1]) or
(p[0]==s[0]-1 and p[1]==s[1]) or
(p[1]==s[1]+1 and p[0]==s[0]) or
(p[1]==s[1]-1 and p[0]==s[0]) or
(p[0]+1==s[0] and p[1]==s[1]) or
(p[0]-1==s[0] and p[1]==s[1]) or
(p[1]+1==s[1] and p[0]==s[0]) or
(p[1]-1==s[1] and p[0]==s[0]))
(Broken up onto multiple lines by enclosing in parentheses, to make it more readable)
Now, you want to check if the distance between the two nodes is exactly 1
, correct? So either the x
or y
coordinates need to be one apart, but not both. That means that if you subtract the two x
s and take the absolute value of that difference, then do the same for the y
s, then add the two differences, it should equal 1
.
We could start by writing this as a for
loop with zip
to iterate through both tuples together, adding up the absolute value of differences:
def prox(p, s):
total_difference = 0
for first, second in zip(p, s):
total_difference += abs(first - second)
return total_difference == 1
This can be condensed using Python’s built-in sum
function and a generator expression:
def prox(p, s):
total_difference = sum(abs(first - second) for first, second in zip(p, s))
return total_difference == 1
Or, skipping the intermediate variable:
def prox(p, s):
return sum(abs(first - second) for first, second in zip(p, s)) == 1
Bonus: this same function generalizes to three (or any number of) dimensions. Probably not useful in this case, but neat.