# ndpar/algorithms

1 parent 455c3ca commit 93bb02293f80369de57ae492143a57a66b59f019 Andrey Paramonov committed May 8, 2010
Showing with 189 additions and 32 deletions.
1. +18 −1 mymath.erl
2. +1 −0 p018.groovy
3. +1 −1 p044.erl
4. +169 −30 recursion.groovy
 @@ -1,5 +1,6 @@ -module(mymath). --export([c/2, ds/1, factorial/1, is_palindrome/1, lcm/2, perms/1, pow/2, primes_upto/1, prod/1]). +-export([c/2, ds/1, factorial/1, factorisation/1, factorisation/3, is_palindrome/1]). +-export([lcm/2, perms/1, pow/2, primes_upto/1, prod/1, ufactorisation/1]). -include_lib("eunit/include/eunit.hrl"). %% Find all prime numbers upto specified value. @@ -90,6 +91,16 @@ is_palindrome([X|Xs]) -> [X|Xs] =:= lists:reverse([X|Xs]); is_palindrome(N) -> is_palindrome(integer_to_list(N)). +%% Factorisation of given integer N +%% +factorisation(N) -> factorisation(N, primes_upto(N), []). +factorisation(1, _, Acc) -> Acc; +factorisation(N, [P|Ps], Acc) when N rem P =:= 0 -> factorisation(N div P, [P|Ps], [P|Acc]); +factorisation(N, [_|Ps], Acc) -> factorisation(N, Ps, Acc). + +ufactorisation(N) -> lists:usort(factorisation(N)). + + %% Tests primes_upto_30_test() -> @@ -119,6 +130,12 @@ c_test() -> factorial_test() -> ?assertEqual(120, factorial(5)). +factorisation_test() -> + ?assertEqual([3,2,2,2], factorisation(24)). + +ufactorisation_test() -> + ?assertEqual([2,3], ufactorisation(24)). + ds_test() -> ?assertEqual(21, ds(1569)).
 @@ -1,5 +1,6 @@ // inspired by // http://blog.dreamshire.com/2009/04/01/project-euler-problem-18-solution +// See also http://en.wikipedia.org/wiki/Dynamic_programming // to solve problem 67 replace file name to triangle67.txt
 @@ -1,6 +1,6 @@ %% Problem %% --------------------- -%% Pentagonal numbers are generated by the formula, Pn=n(3n1)/2. The +%% Pentagonal numbers are generated by the formula, Pn=n(3n-1)/2. The %% first ten pentagonal numbers are: %% %% 1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ...
 @@ -1,22 +1,6 @@ -// http://en.wikipedia.org/wiki/Counting_sort - -def countingSort(list) { - min = list.min(); max = list.max() - range = max - min - counts = new int[range+1] - list.each { counts[it-min]++ } - (1..counts.size()-1).each { counts[it] += counts[it-1] } - - result = new int[list.size()] - (list.size()-1..0).each { - index = list[it] - result[counts[index-min]-- -1] = index - } - result -} - -assert [3,4,4,5,6,7] == countingSort([7,3,6,4,5,4]) - +// ------------------------------------------------------------------ +// Comparison algorithms. Decision-tree model. +// ------------------------------------------------------------------ def swap(list, p, q) { lp = list[p]; list[p] = list[q]; list[q] = lp @@ -27,7 +11,17 @@ swap(list, 0, 3) assert [4,2,3,1,5,6] == list -// http://en.wikipedia.org/wiki/Selection_algorithm +/* + * Partitioning + */ +IntRange.metaClass.random = { -> + from + new Random().nextInt(to - from + 1) +} + +/* randomized partition to get Θ(log n) expected time */ +def partition(list, left, right) { + partition(list, left, right, (left..right).random()) +} def partition(list, left, right, pivotIndex) { pivot = list[pivotIndex] @@ -45,25 +39,170 @@ assert 3 == partition(list, 0, list.size()-1, 4) assert [1,3,2,4,5,6] == list + +/* + * http://en.wikipedia.org/wiki/Quicksort + */ +def quicksort(list) { + quicksort(list, 0, list.size()-1) +} + +def quicksort(list, p, q) { + if (p < q) { + r = partition(list, p, q) + quicksort(list, p, r-1) + quicksort(list, r+1, q) + } + list +} + +assert [1,2,3,4,5,6,7,8] == quicksort([6,1,5,3,8,7,4,2]) +assert [1,2,3,4,5,6,7,8] == quicksort([1,2,3,4,5,6,7,8]) + + + +/* + * http://en.wikipedia.org/wiki/Merge_sort + */ +def mergeSort(list) { + if (list.size() <= 1) return list + def mean = list.size().intdiv(2) + def left = list[0..mean-1] + def right = list[mean..-1] + merge(mergeSort(left), mergeSort(right)) +} + +def merge(left, right) { + def result = [] + while (left.size() > 0 && right.size() > 0) { + if (left[0] < right[0]) result << left.remove(0) + else result << right.remove(0) + } + if (left.size() > 0) return result + left + else return result + right +} + +assert [1,2,3,4,5,6,7,8] == mergeSort([6,1,5,3,8,7,4,2]) + + + +/* + * http://en.wikipedia.org/wiki/Heapsort + * http://datastructurefaqs.blogspot.com/2009/01/sorting-techniques-with-algorithm.html + * No recursion actually + */ +def heapsort(list) { + heapsort(list, list.size()) +} + +def heapsort(list, count) { + heapify(list, count) + def end = count - 1 + while (0 < end) { + swap(list, 0, end) + siftDown(list, 0, end-1) + end = end - 1 + } + list +} + +def heapify(list, count) { + def start = (count - 2).intdiv(2) + while (0 <= start) { + siftDown(list, start, count-1) + start = start - 1 + } +} + +def siftDown(list, start, end) { + def root = start + while (root*2 + 1 <= end) { + def child = root*2 + 1 + if (child < end && list[child] < list[child+1]) child = child + 1 + if (list[root] < list[child]) { + swap(list, root, child) + root = child + } else return list + } +} + +assert [1,2,3,4,5,6,7,8] == heapsort([6,1,5,3,8,7,4,2]) + + + +/* + * http://en.wikipedia.org/wiki/Insertion_sort + */ +def insertionSort(list) { + for (int i in 1..