From d5e7f537e6a4dd45f1a44b7b91de50ed42a84d16 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 15 Aug 2011 06:35:27 -0400 Subject: [PATCH 01/10] working through mit intro to algorithms, first with insertion sort --- insertion_sort01.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 insertion_sort01.py diff --git a/insertion_sort01.py b/insertion_sort01.py new file mode 100644 index 0000000..29ab2f1 --- /dev/null +++ b/insertion_sort01.py @@ -0,0 +1,8 @@ +def insertion_sort(A): + for j in range(1, len(A)): + key = A[j] + i = j - 1 + while i >= 0 and A[i] > key: + A[i + 1] = A[i] + i = i - 1 + A[i + 1] = key From d5f68eaef284f351a4b8fd7679fdbd0f3ac4b5dc Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 15 Aug 2011 06:40:22 -0400 Subject: [PATCH 02/10] adding a readme dangit --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e37292d --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# Practicing Algorithms + +I've been burned enough times when in a room with a bunch of CS Majors... +(grumble.) + +## MIT Open Courseware stuff + +It's just like bookmarks, but on github! + + - Intro. to Algorithms lecture 01 From f0e703c695d15690b3d51048fa9546e137f1d0ef Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 15 Aug 2011 06:47:22 -0400 Subject: [PATCH 03/10] adding a test for first example --- insertion_sort01.py | 12 ++++++------ test_insertion_sort01.py | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 test_insertion_sort01.py diff --git a/insertion_sort01.py b/insertion_sort01.py index 29ab2f1..1fbf329 100644 --- a/insertion_sort01.py +++ b/insertion_sort01.py @@ -1,8 +1,8 @@ -def insertion_sort(A): - for j in range(1, len(A)): - key = A[j] +def insertion_sort(a): + for j in range(1, len(a)): + key = a[j] i = j - 1 - while i >= 0 and A[i] > key: - A[i + 1] = A[i] + while i >= 0 and a[i] > key: + a[i + 1] = a[i] i = i - 1 - A[i + 1] = key + a[i + 1] = key diff --git a/test_insertion_sort01.py b/test_insertion_sort01.py new file mode 100644 index 0000000..47291ee --- /dev/null +++ b/test_insertion_sort01.py @@ -0,0 +1,19 @@ +import unittest + +import insertion_sort01 + + +class Test(unittest.TestCase): + + def test_example(self): + tmpl = [8, 2, 4, 9, 3, 6] + a = tmpl[:] + expected = [2, 3, 4, 6, 8, 9] + + insertion_sort01.insertion_sort(a) + + self.assertEqual(expected, a) + + +if __name__ == '__main__': + unittest.main() From 59465b11529cd0a31fb61174676a0e7ef7e54020 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 15 Aug 2011 06:57:09 -0400 Subject: [PATCH 04/10] adding some more tests for insertion sort to compare performance given inputs of varying sizes --- test_insertion_sort01.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test_insertion_sort01.py b/test_insertion_sort01.py index 47291ee..baff970 100644 --- a/test_insertion_sort01.py +++ b/test_insertion_sort01.py @@ -1,3 +1,4 @@ +import random import unittest import insertion_sort01 @@ -14,6 +15,26 @@ class Test(unittest.TestCase): self.assertEqual(expected, a) + def test_big_example(self): + tmpl = list(range(0, 1000)) + a = tmpl[:] + random.shuffle(a) + expected = tmpl[:] + + insertion_sort01.insertion_sort(a) + + self.assertEqual(expected, a) + + def test_bigger_example(self): + tmpl = list(range(0, 10000)) + a = tmpl[:] + random.shuffle(a) + expected = tmpl[:] + + insertion_sort01.insertion_sort(a) + + self.assertEqual(expected, a) + if __name__ == '__main__': unittest.main() From 828a0287fd802bf6154baec12be32f451cf4d9b8 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 15 Aug 2011 21:59:50 -0400 Subject: [PATCH 05/10] futzing mostly --- insertion_sort01.py | 3 +++ test_insertion_sort01.py | 15 ++++++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/insertion_sort01.py b/insertion_sort01.py index 1fbf329..32cdaea 100644 --- a/insertion_sort01.py +++ b/insertion_sort01.py @@ -1,4 +1,7 @@ +# vim:fileencoding=utf-8 + def insertion_sort(a): + """ Θ(n^2) """ for j in range(1, len(a)): key = a[j] i = j - 1 diff --git a/test_insertion_sort01.py b/test_insertion_sort01.py index baff970..a58c225 100644 --- a/test_insertion_sort01.py +++ b/test_insertion_sort01.py @@ -15,7 +15,7 @@ class Test(unittest.TestCase): self.assertEqual(expected, a) - def test_big_example(self): + def test_100_example(self): tmpl = list(range(0, 1000)) a = tmpl[:] random.shuffle(a) @@ -25,8 +25,17 @@ class Test(unittest.TestCase): self.assertEqual(expected, a) - def test_bigger_example(self): - tmpl = list(range(0, 10000)) + def test_reversed_100_example(self): + tmpl = list(range(0, 1000)) + a = list(reversed(tmpl[:])) + expected = tmpl[:] + + insertion_sort01.insertion_sort(a) + + self.assertEqual(expected, a) + + def test_1000_example(self): + tmpl = list(range(0, 1000)) a = tmpl[:] random.shuffle(a) expected = tmpl[:] From 7f555fbe565f9371c73fca2e65a7caf1f06ad08f Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 15 Aug 2011 22:01:05 -0400 Subject: [PATCH 06/10] renaming now that I am going to be adding merge sort --- insertion_sort01.py => sorting.py | 0 test_insertion_sort01.py => test_sorting.py | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) rename insertion_sort01.py => sorting.py (100%) rename test_insertion_sort01.py => test_sorting.py (77%) diff --git a/insertion_sort01.py b/sorting.py similarity index 100% rename from insertion_sort01.py rename to sorting.py diff --git a/test_insertion_sort01.py b/test_sorting.py similarity index 77% rename from test_insertion_sort01.py rename to test_sorting.py index a58c225..a34694b 100644 --- a/test_insertion_sort01.py +++ b/test_sorting.py @@ -1,17 +1,17 @@ import random import unittest -import insertion_sort01 +import sorting -class Test(unittest.TestCase): +class TestInsertionSort(unittest.TestCase): def test_example(self): tmpl = [8, 2, 4, 9, 3, 6] a = tmpl[:] expected = [2, 3, 4, 6, 8, 9] - insertion_sort01.insertion_sort(a) + sorting.insertion_sort(a) self.assertEqual(expected, a) @@ -21,7 +21,7 @@ class Test(unittest.TestCase): random.shuffle(a) expected = tmpl[:] - insertion_sort01.insertion_sort(a) + sorting.insertion_sort(a) self.assertEqual(expected, a) @@ -30,7 +30,7 @@ class Test(unittest.TestCase): a = list(reversed(tmpl[:])) expected = tmpl[:] - insertion_sort01.insertion_sort(a) + sorting.insertion_sort(a) self.assertEqual(expected, a) @@ -40,7 +40,7 @@ class Test(unittest.TestCase): random.shuffle(a) expected = tmpl[:] - insertion_sort01.insertion_sort(a) + sorting.insertion_sort(a) self.assertEqual(expected, a) From a7f7b48a777a2e8d9fbefa83344cfd05c81c1806 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 15 Aug 2011 22:34:46 -0400 Subject: [PATCH 07/10] working through merge sort --- sorting.py | 38 ++++++++++++++++++++++++++++++++++++++ test_sorting.py | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/sorting.py b/sorting.py index 32cdaea..cbddb26 100644 --- a/sorting.py +++ b/sorting.py @@ -1,4 +1,6 @@ # vim:fileencoding=utf-8 +import math + def insertion_sort(a): """ Θ(n^2) """ @@ -9,3 +11,39 @@ def insertion_sort(a): a[i + 1] = a[i] i = i - 1 a[i + 1] = key + + +def merge_sort(m): + n = len(m) + if n <= 1: + return m + + middle = math.ceil(n / 2) + + left = m[:middle] + right = m[middle:] + + left = merge_sort(left) + right = merge_sort(right) + + return merge(left, right) + + +def merge(left, right): + result = [] + + while len(left) > 0 or len(right) > 0: + if len(left) > 0 and len(right) > 0: + if left[0] <= right[0]: + result.append(left.pop(0)) + else: + result.append(right.pop(0)) + + elif len(left) > 0: + result.append(left.pop(0)) + + elif len(right) > 0: + result.append(right.pop(0)) + + return result + diff --git a/test_sorting.py b/test_sorting.py index a34694b..55bcbf4 100644 --- a/test_sorting.py +++ b/test_sorting.py @@ -45,5 +45,46 @@ class TestInsertionSort(unittest.TestCase): self.assertEqual(expected, a) +class TestMergeSort(unittest.TestCase): + + def test_example(self): + tmpl = [8, 2, 4, 9, 3, 6] + a = tmpl[:] + expected = [2, 3, 4, 6, 8, 9] + + actual = sorting.merge_sort(a) + + self.assertEqual(expected, actual) + + def test_100_example(self): + tmpl = list(range(0, 1000)) + a = tmpl[:] + random.shuffle(a) + expected = tmpl[:] + + actual = sorting.merge_sort(a) + + self.assertEqual(expected, actual) + + def test_reversed_100_example(self): + tmpl = list(range(0, 1000)) + a = list(reversed(tmpl[:])) + expected = tmpl[:] + + actual = sorting.merge_sort(a) + + self.assertEqual(expected, actual) + + def test_1000_example(self): + tmpl = list(range(0, 1000)) + a = tmpl[:] + random.shuffle(a) + expected = tmpl[:] + + actual = sorting.merge_sort(a) + + self.assertEqual(expected, actual) + + if __name__ == '__main__': unittest.main() From c8d657d3c1acb2e046e7bd9e3c49fb1bc6e6112b Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Mon, 15 Aug 2011 23:04:56 -0400 Subject: [PATCH 08/10] adding a benching script to compare sort algorithms --- bench | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100755 bench diff --git a/bench b/bench new file mode 100755 index 0000000..c346b1a --- /dev/null +++ b/bench @@ -0,0 +1,9 @@ +#!/bin/bash + +SETUP="import sorting;import random;l = list(range(0, ${1-5000}));random.shuffle(l)" + +echo -n "insertion sort: " +python -m timeit -s "$SETUP" 'sorting.insertion_sort(l)' + +echo -n "merge sort: " +python -m timeit -s "$SETUP" 'sorting.merge_sort(l)' From 43db7108aa49e030e398e98599c401d9ca408e58 Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Wed, 17 Aug 2011 23:07:18 -0400 Subject: [PATCH 09/10] futzing around with C and Ruby implementations --- .gitignore | 2 ++ Makefile | 14 ++++++++++++++ bench | 7 ++++--- bin/.keep | 0 sorting.rb | 12 ++++++++++++ src/Makefile | 8 ++++++++ src/insertion-sort.c | 38 ++++++++++++++++++++++++++++++++++++++ test_sorting.rb | 20 ++++++++++++++++++++ 8 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 bin/.keep create mode 100644 sorting.rb create mode 100644 src/Makefile create mode 100644 src/insertion-sort.c create mode 100644 test_sorting.rb diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cc694be --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +bin/* +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b8d6031 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +BINDIR := $(PWD)/bin +CFLAGS := -std=c99 -Wall -g + +export BINDIR CFLAGS + + +all: + cd src && $(MAKE) + +clean: + rm -f bin/* + + +.PHONY: all clean diff --git a/bench b/bench index c346b1a..08808c7 100755 --- a/bench +++ b/bench @@ -1,9 +1,10 @@ #!/bin/bash -SETUP="import sorting;import random;l = list(range(0, ${1-5000}));random.shuffle(l)" +SETUP="import sorting" +LIST="$(python -c "import random;l = list(range(0, ${1-5000}));random.shuffle(l);print(l)")" echo -n "insertion sort: " -python -m timeit -s "$SETUP" 'sorting.insertion_sort(l)' +python -m timeit -s "$SETUP" "sorting.insertion_sort($LIST)" echo -n "merge sort: " -python -m timeit -s "$SETUP" 'sorting.merge_sort(l)' +python -m timeit -s "$SETUP" "sorting.merge_sort($LIST)" diff --git a/bin/.keep b/bin/.keep new file mode 100644 index 0000000..e69de29 diff --git a/sorting.rb b/sorting.rb new file mode 100644 index 0000000..f4f68fd --- /dev/null +++ b/sorting.rb @@ -0,0 +1,12 @@ +def insertion_sort(a) + (0..(a.length - 1)).each do |j| + key = a[j] + i = j - 1 + while (i >= 0) && (a[i] > key) + a[i + 1] = a[i] + i = i - 1 + end + a[i + 1] = key + end +end + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..ae4a6d3 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,8 @@ +all: $(BINDIR)/insertion-sort + + +$(BINDIR)/insertion-sort: insertion-sort.c + gcc -o $@ $(CFLAGS) $^ + + +.PHONY: all diff --git a/src/insertion-sort.c b/src/insertion-sort.c new file mode 100644 index 0000000..be8594a --- /dev/null +++ b/src/insertion-sort.c @@ -0,0 +1,38 @@ +#include + +void insertion_sort(int * a, int len_a); + + +int +main(int argc, char ** argv) +{ + int i; + int l[] = {1, 4, 8, 9, 2, 3}; + + insertion_sort(l, 6); + + for (i = 0; i < 6; i++) { + printf("%d\n", l[i]); + } +} + + +void +insertion_sort(int * a, int len_a) +{ + int i, j, key; + + for (j = 1; j < len_a; j++) { + key = a[j]; + i = j - 1; + while ((i >= 0) && (a[i] > key)) { + a[i + 1] = a[i]; + i = i - 1; + } + a[i + 1] = key; + } +} + + +/* vim:filetype=c + */ diff --git a/test_sorting.rb b/test_sorting.rb new file mode 100644 index 0000000..165012f --- /dev/null +++ b/test_sorting.rb @@ -0,0 +1,20 @@ +require 'sorting' + + +def test_insertion_sort + tmpl = [8, 2, 4, 9, 3, 6] + a = Array.copy(tmpl) + expected = [2, 3, 4, 6, 8, 9] + + insertion_sort(a) + + if expected != a + throw Exception.new 'OMG FAIL' + else + puts 'YAY!' + end + +end + + +test_insertion_sort From 0b723f2ae0a20ab8c90c33db8c1d9d9acd76a86f Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Thu, 18 Aug 2011 00:07:47 -0400 Subject: [PATCH 10/10] testing in Ruby the more right-er way --- test_sorting.rb | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/test_sorting.rb b/test_sorting.rb index 165012f..4253cf3 100644 --- a/test_sorting.rb +++ b/test_sorting.rb @@ -1,20 +1,14 @@ +require 'test/unit' require 'sorting' -def test_insertion_sort - tmpl = [8, 2, 4, 9, 3, 6] - a = Array.copy(tmpl) - expected = [2, 3, 4, 6, 8, 9] +class TestSorting < Test::Unit::TestCase + def test_insertion_sort + tmpl = [8, 2, 4, 9, 3, 6] + a = Array.new(tmpl) + expected = [2, 3, 4, 6, 8, 9] - insertion_sort(a) - - if expected != a - throw Exception.new 'OMG FAIL' - else - puts 'YAY!' + insertion_sort(a) + assert_equal(expected, a) end - end - - -test_insertion_sort