Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion merge_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,4 @@ def merge(left, right):
# x100
something_else = [x for x in range(100000)]
random.shuffle(something_else)
merge_sort(something_else)
time_merge_sort(merge_sort(something_else))
2 changes: 1 addition & 1 deletion q_sort.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
78 changes: 78 additions & 0 deletions r_sort.py
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)
Copy link

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?

sequence = [number for x in bins for number in x]
digit += 1
if len(sequence) == len(bins[0]):
return sequence
Copy link

Choose a reason for hiding this comment

The 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])
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This naming is a bit confusing. index usually means "position in a list" but here digit is used for that and index is used to mean 'the integer value I will use to represent that letter'. I know that this value will be used as an index outside of this function, but here the naming is 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)
Copy link

Choose a reason for hiding this comment

The 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):
Copy link

Choose a reason for hiding this comment

The 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)
4 changes: 3 additions & 1 deletion test_merge_sort.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from merge_sort import merge_sort
import random


def test_ordered():
something = [x for x in range(100)]
actual = merge_sort(something)
Expand All @@ -14,9 +15,10 @@ def test_reversed():
expected = [x for x in range(1, 1001)]
assert actual == expected


def test_random():
something_else = [x for x in range(1000)]
random.shuffle(something_else)
actual = merge_sort(something_else)
expected = [x for x in range(0, 1000)]
assert actual == expected
assert actual == expected
59 changes: 59 additions & 0 deletions test_r_sort.py
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']