Created
October 9, 2013 19:07
-
-
Save rylev/6906490 to your computer and use it in GitHub Desktop.
Sort Algorithms in Elixir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Sort Algorithms in Elixir | |
# Selection Sort | |
defmodule Selection do | |
def sort(list) when is_list(list) do | |
do_selection(list, []) | |
end | |
def do_selection([head|[]], acc) do | |
acc ++ [head] | |
end | |
def do_selection(list, acc) do | |
min = min(list) | |
do_selection(:lists.delete(min, list), acc ++ [min]) | |
end | |
defp min([first|[second|[]]]) do | |
smaller(first, second) | |
end | |
defp min([first|[second|tail]]) do | |
min([smaller(first, second)|tail]) | |
end | |
defp smaller(e1, e2) do | |
if e1 <= e2 do e1 else e2 end | |
end | |
end | |
IO.inspect Selection.sort([100,4,10,6,9,3]) #=> [1, 3, 4, 6, 9, 10] | |
# Insertion Sort | |
defmodule Insertion do | |
def sort(list) when is_list(list) do | |
do_sort([], list) | |
end | |
def do_sort(_sorted_list = [], _unsorted_list = [head|tail]) do | |
do_sort([head], tail) | |
end | |
def do_sort(sorted_list, _unsorted_list = [head|tail]) do | |
insert(head, sorted_list) |> do_sort(tail) | |
end | |
def do_sort(sorted_list, _unsorted_list = []) do | |
sorted_list | |
end | |
def insert(elem, _sorted_list = []) do | |
[elem] | |
end | |
def insert(elem, sorted_list) do | |
[min|rest] = sorted_list | |
if min >= elem do [elem|[min|rest]] else [min|insert(elem, rest)] end | |
end | |
end | |
IO.inspect Insertion.sort([1, 2, 100, 3, 4, 1, 200, 45, 6, 10]) #=> [1, 1, 2, 3, 4, 6, 10, 45, 100, 200] | |
# Bubble Sort | |
defmodule Bubble do | |
def sort(list) when is_list(list) do | |
make_pass(do_sort(list, []), list) | |
end | |
def make_pass(bubbled_list, old_list) when bubbled_list != old_list do | |
do_sort(bubbled_list, []) |> make_pass(bubbled_list) | |
end | |
def make_pass(bubbled_list, old_list) when bubbled_list == old_list do | |
bubbled_list | |
end | |
def do_sort(_list = [], _acc) do | |
[] | |
end | |
def do_sort([first|[]], acc) do | |
acc ++ [first] | |
end | |
def do_sort([first|[second|tail]], acc) do | |
[new_first, new_second] = swap(first, second) | |
do_sort([new_second|tail], acc ++ [new_first]) | |
end | |
defp swap(e1, e2) do | |
if e1 <= e2 do [e1, e2] else [e2, e1] end | |
end | |
end | |
IO.inspect Bubble.sort([1, 2, 100, 3, 4, 1, 200, 45, 6, 10]) #=> [1, 1, 2, 3, 4, 6, 10, 45, 100, 200] |
Thanks for putting these together. I made a few changes to your insertion sort and came up with this. It seems to be working as well :)
defmodule Sort.Insertion do
def sort(list) when is_list(list) and length(list) <= 1 do
list
end
def sort(list) when is_list(list) do
[last_elem | first_part_reversed] = Enum.reverse(list)
insert(last_elem, sort(Enum.reverse(first_part_reversed)))
end
defp insert(e, []) do
[e]
end
defp insert(e, [min|rest]) do
cond do
min >= e -> [e,min|rest]
true -> [min|insert(e, rest)]
end
end
end
https://rosettacode.org/wiki/Sorting_algorithms/Bubble_sort#Elixir
defmodule Sort do
def bsort(list) when is_list(list) do
t = bsort_iter(list)
if t == list, do: t, else: bsort(t)
end
def bsort_iter([x, y | t]) when x > y, do: [y | bsort_iter([x | t])]
def bsort_iter([x, y | t]), do: [x | bsort_iter([y | t])]
def bsort_iter(list), do: list
end
https://rosettacode.org/wiki/Sorting_algorithms/Bubble_sort#Elixir
defmodule Sort do def bsort(list) when is_list(list) do t = bsort_iter(list) if t == list, do: t, else: bsort(t) end def bsort_iter([x, y | t]) when x > y, do: [y | bsort_iter([x | t])] def bsort_iter([x, y | t]), do: [x | bsort_iter([y | t])] def bsort_iter(list), do: list end
Nice approach, I would avoid the if..
defmodule Sort do
def bsort(list) when is_list(list) do
t = bsort_iter(list)
(t == list)
|> maybe_sort_again(t)
end
def bsort_iter([x, y | t]) when x > y, do: [y | bsort_iter([x | t])]
def bsort_iter([x, y | t]), do: [x | bsort_iter([y | t])]
def bsort_iter(list), do: list
def maybe_sort_again(false, list), do: bsort(list)
def maybe_sort_again(true, list), do: list
end
Hello @ajuljulian cool stuff.
I made a minor change (pattern matching) to your solution
defmodule Sort.Insertion do
def sort(list) when is_list(list) and length(list) <= 1 do
list
end
def sort(list) when is_list(list) do
[last_elem | first_part_reversed] = Enum.reverse(list)
insert(last_elem, sort(Enum.reverse(first_part_reversed)))
end
defp insert(e, []) do
[e]
end
defp insert(e, [min | rest]) when min >= e do
[e, min | rest]
end
defp insert(e, [min | rest]) do
[min | insert(e, rest)]
end
end
dbg(Sort.Insertion.sort([4, 300, 42, 1, 10]))
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's another bubblesort style that I think is faster: