QuickSort example in Erlang - erlang

I have a question about an Erlang QuickSort implementation:
qsort([]) -> [];
qsort([Pivot|T]) -> qsort([X || X <- T, X < Pivot]) ++ [Pivot] ++ qsort([X || X <- T, X >= Pivot]).
The code above is from a book named Erlang Programming, and I don't understand why the second function has a code snippet X >= Pivot. Why >= but not > when there is already ++[Pivot]++ in the middle of this section of the function?

[Pivot] basically puts the single element Pivot into a list for the purpose of concatenating with the other 2 lists. It doesn't account for other elements with the same value in your input. Therefore, you need to handle it in either the left or right side of your implementation to ensure that such values are not left out when returning the sorted list.
e.g. Let's say your input list is [5,3,6,5,2,7]. There are three sublists that you need to deal with:
[Pivot] = [5]
[X || X <- T, X < Pivot] = [3,2]
[X || X <- T, X > Pivot] = [6,7]
But what about the second "5" in your input? It doesn't figure in any of the above sublists, so when you combine them to get the sorted list out, it's not there any more! Now, if you were to modify either sublist 2 or 3 to check for equality as well, you would get new sublists [3,2,5] or [6,5,7], making sure that all elements in input are considered. Note that it is symmetrical, so you can use "<=" in the left side instead of ">=" in the right side as in your example.

Related

Simple exercise of OCaml about list

Good Morning everyone,
I must do an exercise of Programming, but i'm stuck!
Well, the exercise requires a function that given a list not empty of integers, return the first number with maximum number of occurrences.
For example:
mode [1;2;5;1;2;3;4;5;5;4:5;5] ==> 5
mode [2;1;2;1;1;2] ==> 2
mode [-1;2;1;2;5;-1;5;5;2] ==> 2
mode [7] ==> 7
Important: the exercise must be in functional programming
My idea is:
let rec occurences_counter xs i = match xs with
|[] -> failwith "Error"
|x :: xs when x = i -> 1 + occurences_counter xs i
|x :: xs -> occurences_counter xs i;;
In this function i'm stuck:
let rec mode (l : int list) : int = match l with
|[] -> failwith "Error"
|[x] -> x
|x::y::l when occurences_counter l x >= occurences_counter l y -> x :: mode l
|x::y::l when occurences_counter l y > occurences_counter l x -> y :: mode l;;
Thanks in advance, i'm newbie in programming and in stackoverflow
Sorry for my english
one solution : calculate first a list of couples (number , occurences).
hint : use List.assoc.
Then, loop over that list of couple to find the max occurrence and then return the number.
One suggestion:
your algorithm could be simplified if you sort the list before. This has O(N log(N)) complexity. Then measure the longest sequence of identical numbers.
This is a good strategy because you delegate the hard part of the work to a well known algorithm.
It is probably not the most beautiful code, but here is with what i came up (F#). At first i transform every element to an intermediate format. This format contains the element itself, the position of it occurrence and the amount it occurred.
type T<'a> = {
Element: 'a
Position: int
Occurred: int
}
The idea is that those Records can be added. So you can first transform every element, and then add them together. So a list like
[1;3]
will be first transformed to
[{Element=1;Position=0;Occurred=1}; {Element=3;Position=1;Occurred=1}]
By adding two together you only can add those with the same "Element". The Position with the lower number from both is taken, and Occurred is just added together. So if you for example have
{Element=3;Position=1;Occurred=2} {Element=3;Position=3;Occurred=2}
the result will be
{Element=3;Position=1;Occurred=4}
The idea that i had in mind was a Monoid. But in a real Monoid you had to come up that you also could add different Elements together. By trying some stuff out i feel that the restriction of just adding the same Element where way more easier. I created a small Module with the type. Including some helper functions for creating, adding and comparing.
module Occurred =
type T<'a> = {
Element: 'a
Position: int
Occurred: int
}
let create x pos occ = {Element=x; Position=pos; Occurred=occ}
let sameElements x y = x.Element = y.Element
let add x y =
if not <| sameElements x y then failwith "Cannot add two different Occurred"
create x.Element (min x.Position y.Position) (x.Occurred + y.Occurred)
let compareOccurredPosition x y =
let occ = compare x.Occurred y.Occurred
let pos = compare x.Position y.Position
match occ,pos with
| 0,x -> x * -1
| x,_ -> x
With this setup i now wrote two additional function. One aggregate function that first turns every element into a Occurred.T, group them by x.Element (the result is a list of list). And then it uses List.reduce on the inner list to add the Occurred with the same Element together. The result is a List that Contains only a single Occurred.T for every Element with the first Position and the amount of Occurred items.
let aggregate =
List.mapi (fun i x -> Occurred.create x i 1)
>> List.groupBy (fun occ -> occ.Element)
>> List.map (fun (x,occ) -> List.reduce Occurred.add occ)
You could use that aggregate function to now implement different aggregation logic. In your case you only wanted the one with the highest Occurrences and the lowest position. I wrote another function that did that.
let firstMostOccurred =
List.sortWith (fun x y -> (Occurred.compareOccurredPosition x y) * -1) >> List.head >> (fun x -> x.Element)
One note. Occurred.compareOccurredPosition is written that it sorts everything in ascending order. I think people expecting it in this order to go to the smallest to the biggest element by default. So by default the first element would be the element with the lowest occurrence and the biggest Position. By multiplying the result of it with -1 you turn that function into a descending sorting function. The reason why i did that is that i could use List.head. I also could use List.last to get the last element, but i felt that it would be better not to go through the whole list again just to get the last element. On top of it, you didn't wanted an Occurred.T you wanted the element itself, so i unwrap the Element to get the number.
Here is everything in action
let ll = [
[1;2;5;1;2;3;4;5;5;4;5;5]
[2;1;2;1;1;2]
[-1;2;1;2;5;-1;5;5;2]
[7]
]
ll
|> List.map aggregate
|> List.map firstMostOccurred
|> List.iter (printfn "%d")
This code will now print
5
2
2
7
It has still some rough edges like
Occurred.add throws an exception if you try to add Occurred with different Elements
List.head throws an exception for empty lists
And in both cases no code is written to handle those cases or making sure an exception will not raise.
You need to process you input list while maintaining a state, that stores the number of occurrences of each number. Basically, the state can be a map, where keys are in the domain of list elements, and values are in domain of natural numbers. If you will use Map the algorithm would be of O(NlogN) complexity. You can also use associative list (i.e., a list of type ('key,'value) list) to implement map. This will lead to quadratic complexity. Another approach is to use hash table or an array of the length equal to the size of the input domain. Both will give you a linear complexity.
After you collected the statistics, (i.e., a mapping from element to the number of its occurrences) you need to go through the set of winners, and choose the one, that was first on the list.
In OCaml the solution would look like this:
open Core_kernel.Std
let mode xs : int =
List.fold xs ~init:Int.Map.empty ~f:(fun stat x ->
Map.change stat x (function
| None -> Some 1
| Some n -> Some (n+1))) |>
Map.fold ~init:Int.Map.empty ~f:(fun ~key:x ~data:n modes ->
Map.add_multi modes ~key:n ~data:x) |>
Map.max_elt |> function
| None -> invalid_arg "mode: empty list"
| Some (_,ms) -> List.find_exn xs ~f:(List.mem ms)
The algorithm is the following:
Run through input and compute frequency of each element
Run through statistics and compute spectrum (i.e., a mapping from frequency to elements).
Get the set of elements that has the highest frequency, and find an element in the input list, that is in this set.
For example, if we take sample [1;2;5;1;2;3;4;5;5;4;5;5],
stats = {1 => 2; 2 => 2; 3 => 1; 4 => 2; 5 => 5}
mods = {1 => [3]; 2 => [1;2]; 5 => [5]}
You need to install core library to play with it. Use coretop to play with this function in the toplevel. Or corebuild to compile it, like this:
corebuild test.byte --
if the source code is stored in test.ml

Haskell: laziness affected by parsing method

I have a simple program (it was the second question on CCC 2012) that takes a list of numbers and determines if there is any strictly increasing/decreasing/constant sequence going on. For example:
1 2 3 4 7 8 => Increasing
5 1 -2 -100 => Decreasing
9 9 9 9 9 9 => Constant
1 2 3 4 5 0 => Nothing
I was completely blown away by how smart Haskell was when I coded this. For some reason, when I typed in the numbers interactively into stdin, in was giving me the answer before I had even finished! I thought it was a bug, but then I foolishly realized that Haskell's laziness (I think?) was taking it upon itself to decide that, after I entered 1, 2, 3, 0, no matter what came after, the result would be Nothing, and so it happily outputted that.
Unfortunately, when I changed
let readings = map (read :: (Read a, Num a) => String -> a) $ lines input
to
let readings = parse $ lines input
with parse being a safer method of reading numerical input, implemented as
maybeRead :: (Read a) => String -> Maybe a
maybeRead = fmap fst . listToMaybe . filter (null . dropWhile isSpace . snd) . reads
parse :: (Read a) => [String] -> [a]
parse xs =
let entries = map maybeRead xs
in if all isJust entries
then map fromJust entries
else []
it no longer does this.
Why?
EDIT: More code
-- | Zip together adjacent list elements as pairs in a new list.
zipPairs :: [a] -> [(a, a)]
zipPairs xs = zip (init xs) (tail xs)
-- | Return True if all elements of a given list are equal.
constant :: (Eq a) => [a] -> Bool
constant xs = all (== head xs) (tail xs)
-- | Return the order that the elements of a list are sorted in, if they form
-- a strictly increasing (Just LT), decreasing (Just GT) or constant (Just EQ)
-- sequence. If there is no pattern, return Nothing.
order :: (Ord a) => [a] -> Maybe Ordering
order xs =
let orders = map (\(x, y) -> x `compare` y) (zipPairs xs)
in if constant orders then Just (head orders) else Nothing
and then in mainI have
let readings = parse $ lines input
putStrLn $ if null readings
then "bad input"
else case order readings of
Just EQ -> "Constant"
Just LT -> "Diving"
Just GT -> "Rising"
Nothing -> "Nothing"
If all entries are justs, all isJust entries checks the entire list of entries, which means that the entire list of entries needs to be read in before parse can return.
Okay, longer explanation of why orders is lazy -- all returns False as soon as it reaches a value for which the predicate returns False. Therefore, constant returns false as soon as it hits a value in the tail that isn't equal to the head. order returns as soon as constant returns, so order is lazy.
My first suggestion is stylistic -- look at the zipWith function when calculating orders. let orders = zipWith compare xs $ tail xs should work equally well.
As far as solving your actual problem is concerned, try
order xs = let orders = zipWith (liftM2 compare) xs $ tail xs
in if isJust (head orders) && constant orders
then head orders
else Nothing
Note that you need to import Data.Monad
liftM2 compare will return Just (compare x y) when passed Just x and Just y and Nothing if either or both of its arguments are Nothing.
orders is now a [Maybe Ordering]. If orders is constant (note: (==) works on Maybes) and the first element is a Just, return the first element (which is already a Maybe Ordering). Otherwise, just return Nothing. You could do without the isJust (head orders) call, but adding it should make it return as soon as it sees a Nothing (otherwise, if you give it a list of all Nothings, it will check if every one is Nothing).
You can probably use mapMaybe from Data.Maybe. That is, swap map read with mapMaybe maybeRead. What mapMaybe does is map the function over the list, filter out the Nothings and extract all the remaining values.

What does || mean in Erlang?

I found that there is a || in list manipulation. What does the || mean? Are there any examples about ||?
lists:sum([A*B || {A, B} <- Foo]).
It is used in List comprehensions. List comprehensions is a shorter way to create lists without having to use funs, maps or filters.
From Programming Erlang:
If we have a list L:
L = [1,2,3,4,5].
And we want to double every element, we can do:
lists:map(fun(X) -> 2*X end, L).
But with List comprehensions we can do:
[2*X || X <- L].
Nomenclature most likely comes from mathematical notion of sets, where || means "such that".
e.g. copied from Wikipedia
F = {n2 − 4 : n is an integer; and 0 ≤ n ≤ 19}
In this notation, the colon (":") means "such that", and the description can be interpreted as "F is the set of all numbers of the form n2 − 4, such that n is a whole number in the range from 0 to 19 inclusive." Sometimes the vertical bar ("|") is used instead of the colon.
Applying same thing to
lists:sum([A*B || {A, B} <- Foo]).
means:- generate A*B such that A and B belong to list of tuples "Foo"

return a list consisiting of the elements from tuples

How does one return e.g. the first element of a tuple?
I would like to take a list of 2 element tuples and return the second element of each tuple as a new list.
1> P = {adam,24,{july,29}}.
{adam,24,{july,29}}
2> element(1,P).
adam
3> element(3,P).
{july,29}
See also: http://www.erlang.org/doc/reference_manual/data_types.html#id2259804
you could use lists:map (not so simple like lists comprehension though):
lists:map(fun({_,X}) -> X end, [{a,b},{c,d},{e,f}]).
exactly what you've asked:
666> [element(2,X) || X <- [{1,2},{3,4}]].
[2,4]
Well, true, element/2 + comprehension will work. But the best way is to pattern match:
[ Var2 || {_Var1, Var2} <- [{1,2},{3,4}]]
Every pattern matching is superior to function call, due to code simplicity.
So, above what you have is list comprehension (double pipes inside the list). Before pipes (right hand side) there is generator, left side is a product.
General:
List = [ ReturnedValue = some_function(X) || X <- GeneratorList, X =/= Conditions ]

List comprehension stop generating certain lists if sublist fails on check

I have a code, which generates all the possible variation (with the legnth of N) with repetition.
variation(1, L) ->
[ [H] || H <- L ];
variation(N, L) ->
[[H | T] || H <- L, T <- variation(N - 1, L)].
For variation(3, [1,2,3,4]) it will generate:
[[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,1,4],[1,1,2,1],...]
I would like to check a condition during the generation of the lists. If a sublist fails, it should stop generating lists, that begins with the certain sublist.
For example if [1,1] sublist fails that condition (check), than it should not generate [1,1,1,1], [1,1,1,2] etc (all of those that begin with [1,1]).
I don't know if its possible with 1 list comprehension.
So far, I have this code:
variation(1, L) ->
[ [H] || H <- L ];
variation(N, L) ->
[[H | T] || H <- L, T <- variation(N - 1, L), check([H|T]) ].
This solution will only return those lists, that doesn't fail the condition (it works, but really slow for big input).
If [1,1] fails, it will try to generate [1,1,1,2], but those will fail the check as well. I would need a solution, which doesn't try to generate lists that begin with [1,1,...] (or with a previously failing sublist).
One small detail first: According to your question, variations(3, [1,2,3]). should generate [[1,1,1,1], [1,1,1,2], …] but it actually generates [[1,1,1], [1,1,2], …]. I will assume the code was right and you meant to say that variations(4, [1,2,3]). should generate [[1,1,1,1], [1,1,1,2], …]
I wrote an alternative version of your function that, using a different order on the right side of the LC, avoids generating list when their prefix is already false when checked with check/1:
variation(1, L) ->
[ [Elem] || Elem <- L ];
variation(N, L) ->
[ Init ++ [Last] || Init <- variation(N-1, L), check(Init), Last <- L].
As you can see, since check(Init) happens before Last <- L, Last is only generated if check(Init) == true.
That will likely have the effect you were looking for.
But… be careful. I'm using ++ in the left side of the LC. You should definitely benchmark your code and see if that has an impact on performance or not.
If it does, and only if it does, you might want to consider using something like this:
variation3(1, L) ->
[ [Elem] || Elem <- L ];
variation3(N, L) ->
[ lists:reverse([Last|lists:reverse(Init)]) || Init <- variation2(N-1, L), check(Init), Last <- L].
Maybe worth it, maybe not… you will need to benchmark your stuff to figure that out.

Resources