-
Notifications
You must be signed in to change notification settings - Fork 0
R sort #20
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
base: q-sort
Are you sure you want to change the base?
R sort #20
Changes from all commits
e40c394
7c2d97a
6e19d00
3d59547
0abc47c
d57873a
a3cf2b6
1f934cc
c2014e2
3ac6e29
f288e96
28dd99b
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 |
|---|---|---|
|
|
@@ -57,4 +57,4 @@ def same_maker(how_many): | |
| inputs.append(same_maker(997)) | ||
|
|
||
| for inp in inputs: | ||
| timed_q_sort(inp) | ||
| timed_q_sort(inp) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| #!/usr/bin/env python | ||
| from merge_sort import timed_func | ||
|
|
||
|
|
||
| @timed_func | ||
| def r_sort(sequence): | ||
| digit = 1 | ||
| while True: | ||
| bins = [[] for i in range(10)] | ||
| for x in sequence: | ||
| # the expression in bins returns the number in digit place | ||
| bins[x % 10 ** digit // 10 ** (digit -1)].append(x) | ||
| sequence = [number for x in bins for number in x] | ||
| digit += 1 | ||
| if len(sequence) == len(bins[0]): | ||
| return sequence | ||
|
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. This is a really interesting way of figuring out how to stop the sorting passes. The problem I have with it is that it entails doing one extra pass through the sorting that doesn't really need to happen. Can you figure out before you start how many passes through the sorting step you'll need to make? |
||
|
|
||
|
|
||
| def str_index(_str, digit): | ||
| """Returns the ord of the text at the index of digit""" | ||
| try: | ||
| index = ord(_str[digit]) | ||
|
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. This naming is a bit confusing. |
||
| return index + 1 | ||
| except IndexError: | ||
| return 0 | ||
|
|
||
|
|
||
| @timed_func | ||
| def r_sort_alpha(sequence): | ||
| max_digit = 0 | ||
| # find the length of longest string | ||
| for _str in sequence: | ||
| if len(_str) > max_digit: | ||
| max_digit = len(_str) | ||
|
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. A more pythonic way: max(map(len, sequence)) |
||
| for digit in range(max_digit + 1, -1, -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. good! I'd suggest using xrange instead, but nice job remembering the step argument! |
||
| bins = [[] for i in range(257)] | ||
| for x in sequence: | ||
| index = str_index(x, digit) | ||
| bins[index].append(x) | ||
| sequence = [number for x in bins for number in x] | ||
| return sequence | ||
|
|
||
|
|
||
| @timed_func | ||
| def r_sort_delta(sequence): | ||
| digit = 1 | ||
| while True: | ||
| pos_bins = [[] for i in range(10)] | ||
| neg_bins = [[] for i in range(10)] | ||
| for x in sequence: | ||
| # the expression in bins returns the number in digit place | ||
| if x < 0: | ||
| neg_bins[abs(x) % 10 ** digit // 10 ** (digit -1)].append(x) | ||
| else: | ||
| pos_bins[x % 10 ** digit // 10 ** (digit -1)].append(x) | ||
| sequence = [number for x in neg_bins[::-1] for number in x] | ||
| sequence += [number for x in pos_bins for number in x] | ||
| digit += 1 | ||
| if len(sequence) == len(pos_bins[0]) + len(neg_bins[0]): | ||
| return sequence | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| inputs = [range(500), range(1000)] | ||
| inputs.append([10 ** 1000, 1, 2, 3, 4, 5]) | ||
| inputs.append(range(6)) | ||
| inputs.append(range(1000, 0, -1)) | ||
| inputs.append([10 ** 1000, 1, 2, 3, 4, 5] + range(1000, 0 -1)) | ||
| print "cases for positive integers:" | ||
| for inp in inputs: | ||
| r_sort(inp) | ||
|
|
||
| inputs = [['abcdefghijkabcdefghijk' for x in range(1000)]] | ||
| inputs.append(['abcdefghijkabcdefghijkabcdefghijkabcdefghijk' for x in range(1000)]) | ||
| inputs.append([chr(x) for x in range(256)]) | ||
| print "cases for strings:" | ||
| for inp in inputs: | ||
| r_sort_alpha(inp) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| from r_sort import r_sort_delta, r_sort_alpha, r_sort | ||
| from r_sort import r_sort | ||
|
|
||
|
|
||
| def test_r_one(): | ||
| a = [4, 3, 2, 5, 7, 1, 6] | ||
| a = r_sort(a) | ||
| assert a == [1, 2, 3, 4, 5, 6, 7] | ||
|
|
||
|
|
||
| def test_r_two(): | ||
| a = [5, 5, 5, 5, 5, 5, 5, 5, 5] | ||
| a = r_sort(a) | ||
| assert a == [5, 5, 5, 5, 5, 5, 5, 5, 5] | ||
|
|
||
|
|
||
| def test_r_mixed(): | ||
| a = [1, 2, 5, 4, 4, 6, 7, 9, 8, 0, 0] | ||
| a = r_sort(a) | ||
| assert a == [0, 0, 1, 2, 4, 4, 5, 6, 7, 8, 9] | ||
|
|
||
|
|
||
| def test_r_delta(): | ||
| a = [4, 3, 2, 5, 7, 1, 6] | ||
| a = r_sort_delta(a) | ||
| assert a == [1, 2, 3, 4, 5, 6, 7] | ||
|
|
||
|
|
||
| def test_r_delta_neg(): | ||
| a = [-1, -3, -6, -7, -8, -10, -50] | ||
| a = r_sort_delta(a) | ||
| assert a == [-50, -10, -8, -7, -6, -3, -1] | ||
|
|
||
|
|
||
| def test_r_delta_posneg(): | ||
| a = [1, -3, -6, 7, -8, 10, -50] | ||
| a = r_sort_delta(a) | ||
| assert a == [-50, -8, -6, -3, 1, 7, 10] | ||
|
|
||
|
|
||
| def test_r_alpha_empty(): | ||
| """Test empty strings""" | ||
| a = ['a', 'b', 'aaa', ''] | ||
| a = r_sort_alpha(a) | ||
| assert a == ['', 'a', 'aaa', 'b'] | ||
|
|
||
|
|
||
| def test_r_alpha_shortvlong(): | ||
| """Test that 6 character string comes before 5 char string""" | ||
| a = ['bbbaa', 'b', 'aaabbb', ''] | ||
| a = r_sort_alpha(a) | ||
| assert a == ['', 'aaabbb', 'b', 'bbbaa'] | ||
|
|
||
|
|
||
| def test_r_alpha_zero_char(): | ||
| """Test that 6 character string comes before 5 char string""" | ||
| a = ['\x00', 'b', 'c', ''] | ||
| a = r_sort_alpha(a) | ||
| assert a == ['', '\x00', 'b', 'c'] |
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.
This works, but it has both a modulus operation and a floored division operation. That's going to be pretty slow. Can you find a more efficient operation that would have the same result?