S3Q1 · Cartesian Points Processing¶
⚡ Quick Reference
Function: process_points(points: set, task: str)
import math
def get_angle(x, y):
return math.atan2(y, x)
def process_points(points: set, task: str):
if task == "sort_close_to_y_axis":
return sorted(points, key=lambda p: (abs(p[0]), get_angle(p[0], p[1])))
if task == "closest_point_to_origin":
manhattan = lambda p: abs(p[0]) + abs(p[1])
return min(points, key=lambda p: (manhattan(p), get_angle(p[0], p[1])))
if task == "group_by_quadrant":
quadrant = lambda x, y: (1 if x>0 and y>0 else
2 if x<0 and y>0 else
3 if x<0 and y<0 else 4)
result = {}
for p in points:
q = quadrant(p[0], p[1])
result.setdefault(q, set()).add(p)
return result
Key rules:
- sort_close_to_y_axis: primary key = abs(x), tiebreaker = atan2(y,x) (lower angle first)
- closest_point_to_origin: primary key = Manhattan distance, tiebreaker = atan2(y,x)
- group_by_quadrant: dict {quadrant_num: set_of_points}, omit empty quadrants
Problem Statement¶
Problem
Implement three operations on a set of Cartesian points - sort by distance to y-axis, find closest to origin, and group by quadrant.
Sample data:
Operation 1 - sort_close_to_y_axis¶
Sort by abs(x) ascending; ties broken by polar angle atan2(y,x) ascending:
Tracing:
| Point | abs(x) |
angle atan2(y,x) |
|---|---|---|
(0,7) |
0 | π/2 ≈ 1.571 |
(-1,3) |
1 | ≈ 1.893 |
(2,5) |
2 | ≈ 1.190 ← smallest angle among abs(x)=2 |
(-2,7) |
2 | ≈ 1.848 |
(-2,6) |
2 | ≈ 1.893 |
(-3,-4) |
3 | ≈ -2.214 |
(4,-6) |
4 | ≈ -0.983 |
Result: [(0,7), (-1,3), (2,5), (-2,7), (-2,6), (-3,-4), (4,-6)] ✓
Operation 2 - closest_point_to_origin¶
Manhattan distance = |x| + |y|. Ties broken by lower polar angle:
manhattan = lambda p: abs(p[0]) + abs(p[1])
return min(points, key=lambda p: (manhattan(p), get_angle(p[0], p[1])))
| Point | Manhattan distance |
|---|---|
(-1,3) |
4 ← minimum |
(2,5) |
7 |
(-2,6) |
8 |
(-2,7) |
9 |
(0,7) |
7 |
(-3,-4) |
7 |
(4,-6) |
10 |
Closest: (-1, 3) with distance 4.
Operation 3 - group_by_quadrant¶
Quadrant rules (no points on axes):
| Quadrant | x | y |
|---|---|---|
| 1 | > 0 | > 0 |
| 2 | < 0 | > 0 |
| 3 | < 0 | < 0 |
| 4 | > 0 | < 0 |
quadrant = lambda x, y: (1 if x>0 and y>0 else
2 if x<0 and y>0 else
3 if x<0 and y<0 else 4)
result = {}
for p in points:
q = quadrant(p[0], p[1])
result.setdefault(q, set()).add(p)
return result
From sample:
- Q1: {(2,5)}
- Q2: {(-2,6), (-2,7), (-1,3), (0,7)} ← (0,7) has x=0 but problem says no points on axes - check input
- Q3: {(-3,-4)}
- Q4: {(4,-6)}
Complete solution approaches¶
import math
def get_angle(x, y):
return math.atan2(y, x)
def process_points(points: set, task: str):
if task == "sort_close_to_y_axis":
return sorted(points, key=lambda p: (abs(p[0]), get_angle(p[0], p[1])))
if task == "closest_point_to_origin":
return min(points, key=lambda p: (abs(p[0]) + abs(p[1]), get_angle(p[0], p[1])))
if task == "group_by_quadrant":
def get_quadrant(x, y):
if x > 0 and y > 0: return 1
if x < 0 and y > 0: return 2
if x < 0 and y < 0: return 3
return 4
result = {}
for p in points:
q = get_quadrant(p[0], p[1])
result.setdefault(q, set()).add(p)
return result
import math
def get_angle(x, y):
return math.atan2(y, x)
def process_points(points: set, task: str):
if task == "sort_close_to_y_axis":
def sort_key(p):
return (abs(p[0]), get_angle(p[0], p[1]))
return sorted(points, key=sort_key)
if task == "closest_point_to_origin":
def dist_key(p):
manhattan = abs(p[0]) + abs(p[1])
return (manhattan, get_angle(p[0], p[1]))
return min(points, key=dist_key)
if task == "group_by_quadrant":
result = {}
for p in points:
x, y = p
if x > 0 and y > 0:
q = 1
elif x < 0 and y > 0:
q = 2
elif x < 0 and y < 0:
q = 3
else:
q = 4
if q not in result:
result[q] = set()
result[q].add(p)
return result
import math
def get_angle(x, y):
return math.atan2(y, x)
def process_points(points: set, task: str):
angle = lambda p: get_angle(p[0], p[1])
mdist = lambda p: abs(p[0]) + abs(p[1])
quadrant = lambda p: (1 if p[0]>0 and p[1]>0 else
2 if p[0]<0 and p[1]>0 else
3 if p[0]<0 and p[1]<0 else 4)
if task == "sort_close_to_y_axis":
return sorted(points, key=lambda p: (abs(p[0]), angle(p)))
if task == "closest_point_to_origin":
return min(points, key=lambda p: (mdist(p), angle(p)))
if task == "group_by_quadrant":
result = {}
for p in points:
result.setdefault(quadrant(p), set()).add(p)
return result
Key takeaways¶
Tuple key for multi-criteria sorting/min
key=lambda p: (primary, secondary) sorts first by the primary criterion, then uses the secondary to break ties. Python's tuple comparison is lexicographic - one key handles both criteria cleanly.
atan2(y, x) - note the argument order
math.atan2 takes (y, x) - y first. Getting this backwards gives the wrong angle. The function returns values in [-π, π], with 0 on the positive x-axis and π/2 on the positive y-axis.
setdefault(q, set()).add(p) for grouping
result.setdefault(q, set()) creates an empty set for a new quadrant and returns it (or returns the existing set). Chaining .add(p) adds the point in one line - no if q not in result needed.