-
-
Notifications
You must be signed in to change notification settings - Fork 46.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
added coordinate_compression #9317
base: master
Are you sure you want to change the base?
Changes from all commits
d7fecbe
767e4a5
08ce404
cf2194d
6a0061a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,141 @@ | ||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
Assumption: | ||||||||||||||||||||||||||||||||||||
- The values to compress are assumed to be comparable, | ||||||||||||||||||||||||||||||||||||
- values can be sorted and compared with '<' and '>' operators. | ||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
class CoordinateCompressor: | ||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
A class for coordinate compression. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
This class allows you to compress and decompress a list of values. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Mapping: | ||||||||||||||||||||||||||||||||||||
In addition to compression and decompression, this class maintains a mapping | ||||||||||||||||||||||||||||||||||||
between original values and their compressed counterparts using two data | ||||||||||||||||||||||||||||||||||||
structures: a dictionary `coordinate_map` and a list `reverse_map`. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
- `coordinate_map`: A dictionary that maps original values to their compressed | ||||||||||||||||||||||||||||||||||||
coordinates. Keys are original values, and values are compressed coordinates. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
- `reverse_map`: A list used for reverse mapping, where each index corresponds | ||||||||||||||||||||||||||||||||||||
to a compressed coordinate, and the value at that index is the original value. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Example mapping: | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Original: 10, Compressed: 0 | ||||||||||||||||||||||||||||||||||||
Original: 52, Compressed: 1 | ||||||||||||||||||||||||||||||||||||
Original: 83, Compressed: 2 | ||||||||||||||||||||||||||||||||||||
Original: 100, Compressed: 3 | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
This mapping allows for efficient compression and decompression of values within | ||||||||||||||||||||||||||||||||||||
the list. | ||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
def __init__(self, arr: list[int | float | str]) -> None: | ||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
Initialize the CoordinateCompressor with a list. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Args: | ||||||||||||||||||||||||||||||||||||
arr (list): The list of values to be compressed. | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mypy can check the data types in the function signature but not in the comments. Please do not repeat the data types in both places because readers will be confused if one changes but the other does not.
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
>>> arr = [100, 10, 52, 83] | ||||||||||||||||||||||||||||||||||||
>>> cc = CoordinateCompressor(arr) | ||||||||||||||||||||||||||||||||||||
>>> cc.compress(100) | ||||||||||||||||||||||||||||||||||||
3 | ||||||||||||||||||||||||||||||||||||
>>> cc.compress(52) | ||||||||||||||||||||||||||||||||||||
1 | ||||||||||||||||||||||||||||||||||||
>>> cc.decompress(1) | ||||||||||||||||||||||||||||||||||||
52 | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
self.coordinate_map: dict[ | ||||||||||||||||||||||||||||||||||||
int | float | str, int | ||||||||||||||||||||||||||||||||||||
] = {} # A dictionary to store compressed coordinates | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
self.reverse_map: list[int | float | str] = [-1] * ( | ||||||||||||||||||||||||||||||||||||
len(arr) | ||||||||||||||||||||||||||||||||||||
) # A list to store reverse mapping | ||||||||||||||||||||||||||||||||||||
Comment on lines
+51
to
+60
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not wrap lines for a comment.
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
self.arr = sorted(arr) # The input list | ||||||||||||||||||||||||||||||||||||
self.n = len(arr) # The length of the input list | ||||||||||||||||||||||||||||||||||||
self.compress_coordinates() | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
def compress_coordinates(self) -> None: | ||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
Compress the coordinates in the input list. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
>>> arr = [100, 10, 52, 83] | ||||||||||||||||||||||||||||||||||||
>>> cc = CoordinateCompressor(arr) | ||||||||||||||||||||||||||||||||||||
>>> cc.coordinate_map[83] | ||||||||||||||||||||||||||||||||||||
2 | ||||||||||||||||||||||||||||||||||||
>>> cc.coordinate_map.get(80,-1) # Value not in the original list | ||||||||||||||||||||||||||||||||||||
-1 | ||||||||||||||||||||||||||||||||||||
>>> cc.reverse_map[2] # Value not in the original list | ||||||||||||||||||||||||||||||||||||
83 | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
key = 0 | ||||||||||||||||||||||||||||||||||||
for val in self.arr: | ||||||||||||||||||||||||||||||||||||
if val not in self.coordinate_map: | ||||||||||||||||||||||||||||||||||||
self.coordinate_map[val] = key | ||||||||||||||||||||||||||||||||||||
self.reverse_map[key] = val | ||||||||||||||||||||||||||||||||||||
key += 1 | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
def compress(self, original: float | str) -> int: | ||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
Compress a single value. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Args: | ||||||||||||||||||||||||||||||||||||
original (int | float | str) : The value to compress. | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mypy can check the data types in the function signature but not in the comments. Please do not repeat the data types in both places because readers will be confused if one changes but the other does not.
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||||||||
int: The compressed integer, or -1 if not found in the original list. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
>>> arr = [100, 10, 52, 83] | ||||||||||||||||||||||||||||||||||||
>>> cc = CoordinateCompressor(arr) | ||||||||||||||||||||||||||||||||||||
>>> cc.compress(100) | ||||||||||||||||||||||||||||||||||||
3 | ||||||||||||||||||||||||||||||||||||
>>> cc.compress(7) # Value not in the original list | ||||||||||||||||||||||||||||||||||||
-1 | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
return self.coordinate_map.get(original, -1) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
def decompress(self, num: int) -> int | float | str: | ||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
Decompress a single integer. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Args: | ||||||||||||||||||||||||||||||||||||
num (int): The compressed integer to decompress. | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||||||||
original value (int | float | str) : The original value. | ||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
>>> arr = [100, 10, 52, 83] | ||||||||||||||||||||||||||||||||||||
>>> cc = CoordinateCompressor(arr) | ||||||||||||||||||||||||||||||||||||
>>> cc.decompress(0) | ||||||||||||||||||||||||||||||||||||
10 | ||||||||||||||||||||||||||||||||||||
>>> cc.decompress(5) # Compressed coordinate out of range | ||||||||||||||||||||||||||||||||||||
-1 | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||||||||
return self.reverse_map[num] if num < len(self.reverse_map) else -1 | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
if __name__ == "__main__": | ||||||||||||||||||||||||||||||||||||
from doctest import testmod | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
testmod() | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
arr: list[int | float | str] = [100, 10, 52, 83] | ||||||||||||||||||||||||||||||||||||
cc = CoordinateCompressor(arr) | ||||||||||||||||||||||||||||||||||||
compressed: list[int] = [0] * len(arr) | ||||||||||||||||||||||||||||||||||||
decompressed: list[int | float | str] = [0] * len(arr) | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
for i, original in enumerate(arr): | ||||||||||||||||||||||||||||||||||||
compressed[i] = cc.compress(original) | ||||||||||||||||||||||||||||||||||||
decompressed[i] = cc.decompress(compressed[i]) | ||||||||||||||||||||||||||||||||||||
print(f"Original: {original}, Compressed: {compressed[i]}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a thought... If this is ints on the left and ints on the right, how is a one-to-one mapping compressing anything? Would a dict be as efficient as a dict in this use case?