F# algorithm for hk - f#

Can anyone help me with this problem?
"Realize a function which duplicate each item in a list. You can use List.map"
IN F# sharp language.
And also
"Use the List.init function to generate a list of n random natural numbers between 0 and m."
let makeCopy elem Count =
match Count with
| 0 -> []
| 1 -> elem
let rec dupeElem row count =
match row with
| [] -> []
| hd::tl -> (makeCopy hd count) # dupeElem tl count
//let xs = [1; 2; 3]
//xs |> List.collect (fun x -> List.replicate 3 x)
//val it : int list = [1; 1; 2; 2; 3; 3]

Duplicating the items is pretty straight forward, you just need a recursive function that walks the list.
Generating the random numbers is where you can use List.init to create a new list. You can use the .NET Random class to generate the random numbers you're after.
This gives up the following functions:
let rec duplicateItems list =
match list with
| [] -> []
| head :: tail -> head :: head :: duplicateItems tail
let makeRandomList count upperBound =
let random = Random()
List.init count (fun i -> random.Next(0, upperBound))
You can now generate a random list and pipe it into the duplicate function:
let numbers = makeRandomList 10 20 |> duplicateItems
NOTE: duplicateItems is not tail recursive, so for really large lists this might be an issue. You can get around this by treating the data to duplicate as a sequence:
let duplicateSequence sequence =
seq {
for a in sequence do
yield a
yield a
}
Now we just need to pipe the result into Seq.toList:
let numbers = makeRandomList 10 20 |> duplicateSequence |> Seq.toList
We could also have written makeRandom to return a sequence rather than a list. This would have made the whole computation lazy up until the point we call Seq.toList.

which duplicate each item in a list. You can use List.map
I think your own solution with List.collect is fine. But here's one with List.map:
> let dupe x = List.map (fun s -> [s;s]) x |> List.concat
val dupe : x:'a list -> 'a list
> dupe [1;2;3];;
val it : int list = [1; 1; 2; 2; 3; 3]
Use the List.init function to generate a list of n random natural numbers between 0 and m
I'll show you the general idea, then you can work out the rest, I'm sure. This basically works:
> let rand n max = let r = Random() in List.init n (fun _ -> r.Next(0, max));;
val rand : n:int -> max:int -> int list
> rand 10 12;;
val it : int list = [11; 11; 10; 11; 6; 1; 3; 6; 8; 2]

Related

Finding the Maximum element in a list with pattern matching and recursion F#

I'm trying to find the maximum element in a list without using List.Max for a school assignment using the below given template.
let findMax l =
let rec helper(l,m) = failwith "Not implemented"
match l with
| [] -> failwith "Error -- empty list"
| (x::xs) -> helper(xs,x)
The only solution to the problem I can think of, atm is
let rec max_value1 l =
match l with
|[] -> failwith "Empty List"
|[x] -> x
|(x::y::xs) -> if x<y then max_value1 (y::xs)
else max_value1 (x::xs)
max_value1 [1; 17; 3; 6; 1; 8; 3; 11; 6; 5; 9];;
Is there any way I can go from the function I built to one that uses the template? Thanks!
Your helper function should do the work, the outer function just validates that the list is not empty and if it's not, calls the helper, which should be something like this:
let rec helper (l,m) =
match (l, m) with
| [] , m -> m
| x::xs, m -> helper (xs, max m x)
Note, that you since you're matching against the last argument of the function you can remove it and use function instead of match with:
let rec helper = function
| [] , m -> m
| x::xs, m -> helper (xs, max m x)
let findMax l =
let rec helper(l,m) =
match l with
| [] -> m
| (x::xs) -> helper(xs, if (Some x > m) then Some x else m)
helper (l,None)
Example:
[-2;-6;-1;-9;-56;-3] |> findMax
val it : int option = Some -1
An empty list will return None.
You could go for a tuple to pass both, or simply apply the helper function in your main match (instead of the empty list guard clause). I'm including the answer for someone who might find this question in the future and not have a clear answer.
let findMax l =
let rec walk maxValue = function
| [] -> maxValue
| (x::xs) -> walk (if x > maxValue then x else maxValue) xs
match l with
| [] -> failwith "Empty list"
| (head::tail) -> walk head tail
findMax [1; 12; 3; ] //12
Using fold:
let findMax l = l |> List.fold (fun maxValue x -> if x > maxValue then x else maxValue) (List.head l)
I am not sure of what the exact rules of your assigment are but the max of a list is really just List.reduce max. So
let listMax : int list -> int = List.reduce max
You need the type annotation to please the typechecker.
let inline listMax xs = List.reduce max xs
also works and is generic so it works with e.g. floats and strings as well.

How can I Implement my own List.partition using tail-recursion?

I'm trying to write my own List.partition function for F# practice. Here's my first (naive) attempt:
let rec mypartition_naive func list =
match list with
| [] -> ([],[])
| head::tail ->
let (h1,h2) = mypartition_naive func tail
if func head
then (head::h1,h2)
else (h1,head::h2)
This works, but it's not tail-recursive. I put together a second attempt that uses an accumulator to become tail-recursive:
let mypartition_accumulator func list =
let rec helper acc listinner =
match listinner with
| head::tail ->
let a,b = acc
let newacc = if func head then (head::a,b) else (a,head::b)
helper newacc tail
| _ -> acc
helper ([],[]) list
Strictly speaking, this works: it partitions the list. The problem is that this reverses the order of the lists. I get this:
let mylist = [1;2;3;4;5;6;7;8]
let partitioned = mypartition_accumulator (fun x -> x % 2 = 0) mynums
//partitioned is now ([8; 6; 4; 2], [7; 5; 3; 1])
//I want partitioned to be ([2; 4; 6; 8], [1; 3; 5; 7])
I think that I can use continuation passing to write a tail-recursive partition function that doesn't reverse the list elements, but I don't really understand continuation passing (and I've read a lot about it). How can I write partition using tail-recursive and keeping the list elements in order?
Here's a CPS version, but List.rev is the way to go (see this related answer).
let partition f list =
let rec aux k = function
| h::t -> aux (fun (a, b) ->
k (if f h then h::a, b else a, h::b)) t
| [] -> k ([], [])
aux id list
Although already answered, this question deserves an attempt at an explanation. The accumulator-based, tail-recursive version is basically fold, left-to-right and hence in need of reversal.
let fold folder state list : 'State =
let rec aux state = function
| [] -> state
| h:'T::t -> aux (folder state h) t
aux state list
// val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State
let partitionFold p =
fold (fun (a, b) h -> if p h then h::a, b else a, h::b) ([], [])
>> fun (a, b) -> List.rev a, List.rev b
partitionFold (fun x -> x % 2 = 0) [0..10]
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])
The signature and functionality of fold is now exactly that of List.fold from the standard library.
In contrast, the version in continuation-passing style is equivalent to foldBack (cf. List.foldBack). It iterates recursively from right-to-left (last element first), and thus obtains the desired order right away.
let foldBack folder list state : 'State =
let rec aux k = function
| [] -> k state
| h:'T::t -> aux (folder h >> k) t
aux id list
// val foldBack :
// folder:('T -> 'State -> 'State) -> list:'T list -> state:'State -> 'State
let partitionFoldBack p list =
foldBack (fun h (a, b) -> if p h then h::a, b else a, h::b) list ([], [])
partitionFoldBack (fun x -> x % 2 = 0) [0..10]
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])

Finding (and removing) repeating pairs in array

I want a way to get rid of repeating pairs in an array. For my problem, the pairs will be consecutive, and there will be at most one repeating pair.
My current implementation seems too complicated. The elements 3 and 4 form what I'm calling a repeating pair in arr1 below. As a pair, they only appear once in the desired output, arr2. What are some more efficient ways?
let arr1=[|4; 2; 3; 4; 3; 4; 1|]
let n=arr1.Length
let iPlus2IsEqual=Array.map2 (fun x y -> x=y) arr1.[2..] arr1.[..(n-3)]
let consecutive=Array.map2 (fun x y -> x && y) iPlus2IsEqual.[1..] iPlus2IsEqual.[..(n-4)] |> Array.tryFindIndex (fun x -> x)
let dup=if consecutive.IsSome then consecutive.Value+1 else n-1
let arr2=if dup>=n-3 then arr1.[..dup] else Array.append arr1.[..dup] arr1.[(dup+3)..]
>
val arr2 : int [] = [|4; 2; 3; 4; 1|]
We can use recursion like so (it will get multiple repeats for free too)
let rec filterrepeats l =
match l with
|a::b::c::d::t when a=c && b=d -> a::b::(filterrepeats t)
|h::t ->h::(filterrepeats t)
|[] -> []
> filterrepeats [4;2;3;4;3;4;1];;
val it : int list = [4; 2; 3; 4; 1]
This works on lists, so you will need to add a call to Array.toList before you run it.
The above is not tail recursive as the compiler doesn't know what goes on the right hand side of h::(filterrepeats t) until after the function call. You can solve this by using an accumulator like so:
let rec filterrepeats l =
let rec loop l acc =
match l with
|a::b::c::d::t when a=c && b=d ->loop t (b::a::acc)
|h::t ->loop t (h::acc)
|[] -> acc
loop (List.rev l) []
For large arrays this is around 13x faster than your solution:
let inline tryFindDuplicatedPairIndex (xs: _ []) =
let rec loop i x0 x1 x2 =
if i < xs.Length-4 then
let x3 = xs.[i+3]
if x0=x2 && x1=x3 then Some i else
loop (i+1) x1 x2 x3
else None
if xs.Length < 4 then None else
loop 0 xs.[0] xs.[1] xs.[2]
let inline removeDuplicatedPair (xs: _ []) =
match tryFindDuplicatedPairIndex xs with
| None -> Array.copy xs
| Some i ->
let ys = Array.zeroCreate (xs.Length-2)
for j=0 to i-1 do
ys.[j] <- xs.[j]
for j=i+2 to xs.Length-1 do
ys.[j-2] <- xs.[j]
ys
I use inline and test elements individually (i.e. rather than as a tuple: (x0,x1) = (x2,x3)) to try to prevent = from being a generic equality test because that is very slow. I've reused previous array lookups from one iteration to the next. I copy the input array if the output is identical to the input and pre-allocate an array with n-2 elements otherwise. I've hand-rolled the copying to my pre-allocated array to avoid creating any garbage (e.g. instead of Array.append of two slices).
No stack overflow with large list (length >= 100K) and remove all duplicate pairs
let rec distinctPairs list =
List.foldBack (fun x (l,r) -> x::r, l) list ([],[])
|> fun (odds, evens) -> List.zip odds evens
|> Seq.distinct
Not very fast, 1M list take 500ms, anyway faster ?
Only work for list with even length

In F#, is there a functional way to converting a flat array of items into an array of a group of items?

In F#, imagine we have an array of bytes representing pixel data with three bytes per pixel in RGB order:
[| 255; 0; 0; //Solid red
0; 255; 0; //Solid green
0; 0; 255; //Solid blue
1; 72; 9;
34; 15; 155
... |]
I'm having a hard time knowing how to functionally operate on this data as-is, since a single item is really a consecutive block of three elements in the array.
So, I need to first group the triples in the array into something like this:
[|
[| 255; 0; 0 |];
[| 0; 255; 0 |];
[| 0; 0; 255 |];
[| 1; 72; 9 |];
[| 34; 15; 155 |]
... |]
Now, gathering up the triples into sub-arrays is easy enough to do with a for loop, but I'm curious--is there a functional way to gather up groups of array elements in F#? My ultimate goal is not simply to convert the data as illustrated above, but to solve the problem in a more declarative and functional manner. But I have yet to find an example of how to do this without an imperative loop.
kvb's answer may not give you what you want. Seq.windowed returns a sliding window of values, e.g., [1; 2; 3; 4] becomes [[1; 2; 3]; [2; 3; 4]]. It seems like you want it split into contiguous chunks. The following function takes a list and returns a list of triples ('T list -> ('T * 'T * 'T) list).
let toTriples list =
let rec aux f = function
| a :: b :: c :: rest -> aux (fun acc -> f ((a, b, c) :: acc)) rest
| _ -> f []
aux id list
Here's the inverse:
let ofTriples triples =
let rec aux f = function
| (a, b, c) :: rest -> aux (fun acc -> f (a :: b :: c :: acc)) rest
| [] -> f []
aux id triples
EDIT
If you're dealing with huge amounts of data, here's a sequence-based approach with constant memory use (all the options and tuples it creates have a negative impact on GC--see below for a better version):
let (|Next|_|) (e:IEnumerator<_>) =
if e.MoveNext() then Some e.Current
else None
let (|Triple|_|) = function
| Next a & Next b & Next c -> Some (a, b, c) //change to [|a;b;c|] if you like
| _ -> None
let toSeqTriples (items:seq<_>) =
use e = items.GetEnumerator()
let rec loop() =
seq {
match e with
| Triple (a, b, c) ->
yield a, b, c
yield! loop()
| _ -> ()
}
loop()
EDIT 2
ebb's question about memory use prompted me to test and I found toSeqTriples to be slow and cause surprisingly frequent GCs. The following version fixes those issues and is almost 4x faster than the list-based version.
let toSeqTriplesFast (items:seq<_>) =
use e = items.GetEnumerator()
let rec loop() =
seq {
if e.MoveNext() then
let a = e.Current
if e.MoveNext() then
let b = e.Current
if e.MoveNext() then
let c = e.Current
yield (a, b, c)
yield! loop()
}
loop()
This has relatively constant memory usage vs a list or array-based approach because a) if you have a seq to start with the entire sequence doesn't have to be slurped into a list/array; and b) it also returns a sequence, making it lazy, and avoiding allocating yet another list/array.
I need to first group the triples in the array into something like this:
If you know they will always be triples then representing then as a tuple int * int * int is more "typeful" than using an array because it conveys the fact that there are only ever exactly three elements.
Other people have described various ways to massage the data but I would actually recommend not bothering (unless there is more to this than you have described). I would opt for a function to destructure your array as-is instead:
let get i = a.[3*i], a.[3*i+1], a.[3*i+2]
If you really want to change the representation then you can now do:
let b = Array.init (a.Length/3) get
The answer really depends upon what you want to do next though...
(Hat tip: Scott Wlaschin) As of F# 4.0, you can use Array.chunkBySize(). It does exactly what you want:
let bs = [| 255; 0; 0; //Solid red
0; 255; 0; //Solid green
0; 0; 255; //Solid blue
1; 72; 9;
34; 15; 155 |]
let grouped = bs |> Array.chunkBySize 3
// [| [|255; 0; 0|]
// [| 0; 255; 0|]
// [| 0; 0; 255|]
// [| 1; 72; 9|]
// [| 34; 15; 155|] |]
The List and Seq modules also have chunkBySize() in F# 4.0. As of this writing, the docs at MSDN don't show chunkBySize() anywhere, but it's there if you're using F# 4.0.
UPDATE: As pointed out by Daniel, this answer is wrong because it creates a sliding window.
You can use the Seq.windowed function from the library. E.g.
let rgbPix = rawValues |> Seq.windowed 3
This returns a sequence rather than an array, so if you need random access, you could follow that with a call to Seq.toArray.
Another approach, that takes and yields arrays directly:
let splitArrays n arr =
match Array.length arr with
| 0 ->
invalidArg "arr" "array is empty"
| x when x % n <> 0 ->
invalidArg "arr" "array length is not evenly divisible by n"
| arrLen ->
let ret = arrLen / n |> Array.zeroCreate
let rec loop idx =
ret.[idx] <- Array.sub arr (idx * n) n
match idx + 1 with
| idx' when idx' <> ret.Length -> loop idx'
| _ -> ret
loop 0
Or, yet another:
let splitArray n arr =
match Array.length arr with
| 0 ->
invalidArg "arr" "array is empty"
| x when x % n <> 0 ->
invalidArg "arr" "array length is not evenly divisible by n"
| arrLen ->
let rec loop idx = seq {
yield Array.sub arr idx n
let idx' = idx + n
if idx' <> arrLen then
yield! loop idx' }
loop 0 |> Seq.toArray

How can I remove duplicates in an F# sequence without using references

I have a sorted sequence and want to go through it and return the unique entries in the sequence. I can do it using the following function, but it uses reference variables and I don't think it's the correct way of solving the problem.
let takeFirstCell sectors =
let currentRNCId = ref -1
let currentCellId = ref -1
seq {
for sector in sectors do
if sector.RNCId <> !currentRNCId || sector.CellId <> !currentCellId then
currentRNCId := sector.RNCId
currentCellId := sector.CellId
yield sector
}
How can I do this in a functional way?
[1;1;1;2;2;2;3;3;3]
|> Seq.distinctBy id
|> printfn "%A"
Seq.distinct (1::[1..5]) returns seq [1; 2; 3; 4; 5]. Is that what you meant?
distinct and distinctBy both use Dictionary and therefore require hashing and a bit of memory for storing unique items. If your sequence is already sorted, you can use the following approach (similar to yours). It's nearly twice as fast and has constant memory use, making it usable for sequences of any size.
let distinctWithoutHash (items:seq<_>) =
seq {
use e = items.GetEnumerator()
if e.MoveNext() then
let prev = ref e.Current
yield !prev
while e.MoveNext() do
if e.Current <> !prev then
yield e.Current
prev := e.Current
}
let items = Seq.init 1000000 (fun i -> i / 2)
let test f = items |> f |> (Seq.length >> printfn "%d")
test Seq.distinct //Real: 00:00:01.038, CPU: 00:00:01.435, GC gen0: 47, gen1: 1, gen2: 1
test distinctWithoutHash //Real: 00:00:00.622, CPU: 00:00:00.624, GC gen0: 44, gen1: 0, gen2: 0
I couldn't figure out a way to use mutables instead of refs (short of hand-coding an enumerator), which I'm sure would speed it up considerably (I tried it--it makes no difference).
Just initialize a unique collection (like a set) with the sequence like this:
set [1; 2; 3; 3; 4; 5; 5];;
=> val it : Set<int> = set [1; 2; 3; 4; 5]
In my case I could not use Seq.distinct because I needed to preserve order of list elements.
I used solution from http://ocaml.org/learn/tutorials/99problems.html.
I think it is quite short
let rec compress = function
| a :: (b :: _ as t) -> if a = b then compress t else a :: compress t
| smaller -> smaller
The solution below, preserves order of elements and returns only the first occurance of an element in a generic list. Of course this generates a new List with the redundant items removed.
// **** Returns a list having subsequent redundant elements removed
let removeDuplicates(lst : 'a list) =
let f item acc =
match acc with
| [] -> [item]
| _ ->
match List.exists(fun x -> x = item) acc with
| false -> item :: acc
| true -> acc
lst
|> List.rev
|> fun x -> List.foldBack f x []
|> List.rev
// **** END OF FUNCTION removeDuplicates
val removeDuplicates : 'a list -> 'a list when 'a : equality
val testList : int list = [1; 4; 3; 1; 2; 2; 1; 1; 3; 4; 3]
val tryAbove : int list = [1; 4; 3; 2]

Resources