I have to write a program which give in output a tuple with: min and max of a not-empty list and the value that appears most often.
In particular:
min_max [1;0;-1;2;0;-4] ==> (-4; 2)
min_max: int list -> (int * int)
mode [-1;2;1;2;5;-1;5;5;2] ==> 2
mode: int list -> int
This is the code that I wrote for max (min is almost equal) but how can I do to receive as output a tuple with the two values?
let rec max_list xs =
match xs with
| [] -> failwith "xs" "Empty list"
| [x] -> x
| x1::x2::xs' -> max_list((max2 x1 x2)::xs');;
I'll take the first suggestion from #Mark Seemann's answer and run with it, in order to make it generic, working with any collection type, and handle the case of the empty collection sensibly.
let tryMinMax xs =
Seq.fold (function
| Some(mn, mx) -> fun i -> Some(min mn i, max mx i)
| None -> fun i -> Some(i, i) ) None xs
[1;0;-1;2;0;-4]
|> tryMinMax
// val it : (int * int) option = Some (-4, 2)
For the most frequent part of the question:
let mostFrequent xs =
xs
|> Seq.countBy id
|> Seq.maxBy snd
|> fst
[1;0;-1;2;0;-4]
|> mostFrequent
// val it : int = 0
let minMax xs =
xs
|> List.fold
(fun (mn, mx) i -> min mn i, max mx i)
(System.Int32.MaxValue, System.Int32.MinValue)
Not particularly efficient, but fun to write:
let mode xs =
xs
|> List.groupBy id
|> List.map (fun (i, is) -> i, Seq.length is)
|> List.maxBy snd
|> fst
Option without the use of standard modules:
open System
let tryMinMax xs =
let rec minMax xs mn mx =
match xs with | [] -> mn, mx | h::t -> minMax t (min mn h) (max mx h)
match xs with | [] -> None | _ -> Some(minMax xs Int32.MaxValue Int32.MinValue)
dotnetfiddle
On the second question - show their attempts to solve.
Related
I have the following code:
let orders = Array2D.init<AnalyzerOrder> (sentimentRanges |> Seq.length) (triggerRanges |> Seq.length) (fun x y -> AnalyzerOrder.empty)
sentimentRanges |> Seq.iteri (fun x sentimentPeriod ->
triggerRanges |> Seq.iteri (fun y triggerPeriod ->
(
let settings =
{
...
}
orders.[x, y] <- settings
)
)
)
It takes 2 sequences, and create an order list with all the combinations and put them in a grid.
Is there a built-in way to create all the combinations from 2 sequences?
When you look at the implementation of Seq.allPairs you will discover that it boils down to Seq.collect for the outer loop and Seq.cache/Seq.map for the inner. This can be generalized to two functions mapc/iterc, who take a function f:('a -> 'b -> 'c) or action f:('a -> 'b -> unit) as their first argument.
let mapc f xs ys = Seq.collect (fun x -> Seq.map (f x) (Seq.cache ys)) xs
// val mapc : f:('a -> 'b -> 'c) -> xs:seq<'a> -> ys:seq<'b> -> seq<'c>
let iterc f xs ys = Seq.iter (fun x -> Seq.iter (f x) (Seq.cache ys)) xs
// val iterc : f:('a -> 'b -> unit) -> xs:seq<'a> -> ys:seq<'b> -> unit
We could use them to generate the hyperinflation sequence for banknotes (OEIS A051109), or - more to the question - imperatively fill the values of an [,].
mapc (*) (Seq.initInfinite (pown 10I)) [1I; 2I; 5I] |> Seq.take 10 |> Seq.toList
// val it : System.Numerics.BigInteger list =
// [1; 2; 5; 10; 20; 50; 100; 200; 500; 1000]
let a2 = Array2D.zeroCreate 3 3
iterc (fun i j -> a2.[i,j] <- 1) [0..2] [0..2]
An example:
let initArray f s1 s2 = Array2D.init (Array.length s1) (Array.length s2) (fun a b -> f s1.[a] s2.[b] )
initArray (+) [|1;2;3|] [|1;2;3;4|] //where f is a sum function in this case
If you just to list all combinations, you can use the built-in function Seq.allPairs (exists in Array and List variants as well). If you want to create a two-dimensional array, you should do as #FRocha suggests.
I'm quite a newbie at F# and want to find how many times a value x has occurred in a list ys
So for example multiplicity (2, [1;2;3;4;2]) returns 2. The code I've written below returns 4 on the above example. What am I missing?
let rec multiplicity (x, ys) =
match ys with
| [] -> 0
| y::tail when x=y -> x + multiplicity(x, tail)
| y::tail -> multiplicity(x, tail)
If you're not writing this as a recursive function as a learning exercise, it's probably more idiomatic to use the built-in collection functions:
[1;2;3;4;2] |> Seq.filter ((=) 2) |> Seq.length
[1;2;3;4;2] |> List.sumBy (fun x -> if x = 2 then 1 else 0)
Alright, this is a good example of why it's always a good idea to write down a problem/question.
I figured out, I should do this instead:
let rec multiplicity (x, ys) =
match ys with
| [] -> 0
| y::tail when x=y -> 1 + multiplicity(x, tail)
| y::tail -> multiplicity(x, tail)
It should be 1 and not x, which is added to the recursive call, doh.
I find it's a good idea to replace recursion with fold, so here is another version:
let xs = [1;2;3;4;2]
(0,xs) ||> List.fold (fun acc elem -> match elem with
| 2 -> acc + 1
| _ -> acc)
You can also use countBy, which will return a list of tuples with true and false.
xs |> List.countBy (fun x -> x = 2)
This is a reference question to this: StackOverflow in continuation monad
with whom I played a little and would need a few clarifications.
1) I suppose this:
member this.Delay(mk) = fun c -> mk () c
makes the behavior in computational workflow do the diffrence as showed by toyvo between these:
cBind (map xs) (fun xs -> cReturn (f x :: xs))
cBind (fun c -> map xs c) (fun xs -> cReturn (f x :: xs))
So I don't exactly understand what is the trick, when
(fun c -> map xs c) is only different notation of (map xs)
2) Inference issue. - In OP's second map example I found out it doesn't compile due to inference problem with v value, because it infers f as a -> b list, instead of desired a -> b. Why it infers in this way? In case let v = f x it would infer well.
3) It seems to me that VS shows inaccurate type signatures in the tooltips:
return type of the monad's Return is: ('e->'f)->f, while the return type of the Bind is only 'c->'b. -It seems it simplify ('e->'f) to only c in the Bind case, or am I missing something here?
Thanks for the clarification,
tomas
Edit - testing dump:
let cReturn x = fun k -> k x
let cBind m f =
printfn "cBind %A" <| m id
fun c -> m (fun a -> f a c)
let map_fixed f xs =
let rec map xs =
printfn "map %A" xs
match xs with
| [] -> cReturn []
| x :: xs -> cBind (fun c -> map xs c) (fun xs -> cReturn (f x :: xs))
map xs (fun x -> x)
let map f xs =
let rec map xs =
printfn "map %A" xs
match xs with
| [] -> cReturn []
| x :: xs -> cBind (map xs) (fun xs -> cReturn (f x :: xs))
map xs (fun x -> x)
[1..2] |> map_fixed ((+) 1) |> printfn "%A"
[1..2] |> map ((+) 1) |> printfn "%A"
map_fixed:
map [1; 2]
map [2]
map []
cBind []
map []
cBind [3]
map [2]
map []
cBind []
map []
[2; 3]
map:
map [1; 2]
map [2]
map []
cBind []
cBind [3]
[2; 3]
Edit to question 2:
let map f xs =
let rec map xs =
cont {
match xs with
| [] -> return []
| x :: xs ->
let v = f x // Inference ok
//let! v = cont { return f x } // ! Inference issue - question 2
let! xs = map xs
return v :: xs
}
map xs id
The issue is exactly that fun c -> map xs c is not the same as map xs. They have the same "meaning" in some sense, but their runtime semantics are different. In the latter case, evaluating the expression results in an immediate call to the map function with xs as an argument (returning another function as the result). On the other hand, evaluating fun c -> map xs c does not result in an immediate call to map! The call to map is delayed until the resulting function is actually applied. This is the critical difference that prevents a stack overflow.
Regarding your other questions, I can't quite make out what you're asking in your second question. For your third question, the compiler has inferred the most general type possible for Bind. You're right that the traditional type that you might expect is more specific than this, but it's not really a problem that you can call Bind in a wider set of contexts than is strictly necessary. And if you really want a more specific type, you can always add annotations to constrain the signature.
For cartesian production there is a good enough function - sequence which defined like that:
let rec sequence = function
| [] -> Seq.singleton []
| (l::ls) -> seq { for x in l do for xs in sequence ls do yield (x::xs) }
but look at its result:
sequence [[1..2];[1..10000]] |> Seq.skip 1000 ;;
val it : seq = seq [[1; 1001]; [1; 1002]; [1; 1003]; [1; 1004]; ...]
As we can see the first "coordinate" of the product alters very slowly and it will change the value when the second list is ended.
I wrote my own sequence as following (comments below):
/// Sum of all producted indeces = n
let rec hyper'plane'indices indexsum maxlengths =
match maxlengths with
| [x] -> if indexsum < x then [[indexsum]] else []
| (i::is) -> [for x in [0 .. min indexsum (i-1)] do for xs in hyper'plane'indices (indexsum-x) is do yield (x::xs)]
| [] -> [[]]
let finite'sequence = function
| [] -> Seq.singleton []
| ns ->
let ars = [ for n in ns -> Seq.toArray n ]
let length'list = List.map Array.length ars
let nmax = List.max length'list
seq {
for n in [0 .. nmax] do
for ixs in hyper'plane'indices n length'list do
yield (List.map2 (fun (a:'a[]) i -> a.[i]) ars ixs)
}
The key idea is to look at (two) lists as at (two) orthogonal dimensions where every element marked by its index in the list. So we can enumerate all elements by enumerating every element in every section of cartesian product by hyper plane (in 2D case this is a line). In another words imagine excel's sheet where first column contains values from [1;1] to [1;10000] and second - from [2;1] to [2;10000]. And "hyper plane" with number 1 is the line that connects cell A2 and cell B1. For the our example
hyper'plane'indices 0 [2;10000];; val it : int list list = [[0; 0]]
hyper'plane'indices 1 [2;10000];; val it : int list list = [[0; 1]; [1; 0]]
hyper'plane'indices 2 [2;10000];; val it : int list list = [[0; 2]; [1; 1]]
hyper'plane'indices 3 [2;10000];; val it : int list list = [[0; 3]; [1; 2]]
hyper'plane'indices 4 [2;10000];; val it : int list list = [[0; 4]; [1; 3]]
Well if we have indeces and arrays that we are producing from the given lists than we can now define sequence as {all elements in plane 0; than all elements in plane 1 ... and so on } and get more volatile function than original sequence.
But finite'sequence turned out very gluttonous function. And now the question. How I can improve it?
With best wishes, Alexander. (and sorry for poor English)
Can you explain what exactly is the problem - time or space complexity or performance? Do you have a specific benchmark in mind? I am not sure how to improve on the time complexity here, but I edited your code a bit to remove the intermediate lists, which might help a bit with memory allocation behavior.
Do not do this:
for n in [0 .. nmax] do
Do this instead:
for n in 0 .. nmax do
Here is the code:
let rec hyper'plane'indices indexsum maxlengths =
match maxlengths with
| [] -> Seq.singleton []
| [x] -> if indexsum < x then Seq.singleton [indexsum] else Seq.empty
| i :: is ->
seq {
for x in 0 .. min indexsum (i - 1) do
for xs in hyper'plane'indices (indexsum - x) is do
yield x :: xs
}
let finite'sequence xs =
match xs with
| [] -> Seq.singleton []
| ns ->
let ars = [ for n in ns -> Seq.toArray n ]
let length'list = List.map Array.length ars
let nmax = List.max length'list
seq {
for n in 0 .. nmax do
for ixs in hyper'plane'indices n length'list do
yield List.map2 Array.get ars ixs
}
Does this fare any better? Beautiful problem by the way.
UPDATE: Perhaps you are more interested to mix the sequences fairly than in maintaining the exact formula in your algorithm. Here is a Haskell code that mixes a finite number of possibly infinite sequences fairly, where fairness means that for every input element there is a finite prefix of the output sequence that contains it. You mention in the comment that you have a 2D incremental solution that is hard to generalize to N dimensions, and the Haskell code does exactly that:
merge :: [a] -> [a] -> [a]
merge [] y = y
merge x [] = x
merge (x:xs) (y:ys) = x : y : merge xs ys
prod :: (a -> b -> c) -> [a] -> [b] -> [c]
prod _ [] _ = []
prod _ _ [] = []
prod f (x:xs) (y:ys) = f x y : a `merge` b `merge` prod f xs ys where
a = [f x y | x <- xs]
b = [f x y | y <- ys]
prodN :: [[a]] -> [[a]]
prodN [] = [[]]
prodN (x:xs) = prod (:) x (prodN xs)
I have not ported this to F# yet - it requires some thought as sequences do not match to head/tail very well.
UPDATE 2:
A fairly mechanical translation to F# follows.
type Node<'T> =
| Nil
| Cons of 'T * Stream<'T>
and Stream<'T> = Lazy<Node<'T>>
let ( !! ) (x: Lazy<'T>) = x.Value
let ( !^ ) x = Lazy.CreateFromValue(x)
let rec merge (xs: Stream<'T>) (ys: Stream<'T>) : Stream<'T> =
lazy
match !!xs, !!ys with
| Nil, r | r, Nil -> r
| Cons (x, xs), Cons (y, ys) -> Cons (x, !^ (Cons (y, merge xs ys)))
let rec map (f: 'T1 -> 'T2) (xs: Stream<'T1>) : Stream<'T2> =
lazy
match !!xs with
| Nil -> Nil
| Cons (x, xs) -> Cons (f x, map f xs)
let ( ++ ) = merge
let rec prod f xs ys =
lazy
match !!xs, !!ys with
| Nil, _ | _, Nil -> Nil
| Cons (x, xs), Cons (y, ys) ->
let a = map (fun x -> f x y) xs
let b = map (fun y -> f x y) ys
Cons (f x y, a ++ b ++ prod f xs ys)
let ofSeq (s: seq<'T>) =
lazy
let e = s.GetEnumerator()
let rec loop () =
lazy
if e.MoveNext()
then Cons (e.Current, loop ())
else e.Dispose(); Nil
!! (loop ())
let toSeq stream =
stream
|> Seq.unfold (fun stream ->
match !!stream with
| Nil -> None
| Cons (x, xs) -> Some (x, xs))
let empty<'T> : Stream<'T> = !^ Nil
let cons x xs = !^ (Cons (x, xs))
let singleton x = cons x empty
let rec prodN (xs: Stream<Stream<'T>>) : Stream<Stream<'T>> =
match !!xs with
| Nil -> singleton empty
| Cons (x, xs) -> prod cons x (prodN xs)
let test () =
ofSeq [
ofSeq [1; 2; 3]
ofSeq [4; 5; 6]
ofSeq [7; 8; 9]
]
|> prodN
|> toSeq
|> Seq.iter (fun xs ->
toSeq xs
|> Seq.map string
|> String.concat ", "
|> stdout.WriteLine)
Using the following continuation monad:
type ContinuationMonad() =
member this.Bind (m, f) = fun c -> m (fun a -> f a c)
member this.Return x = fun k -> k x
let cont = ContinuationMonad()
I fail to see why the following gives me a stack overflow:
let map f xs =
let rec map xs =
cont {
match xs with
| [] -> return []
| x :: xs ->
let! xs = map xs
return f x :: xs
}
map xs id;;
let q = [1..100000] |> map ((+) 1)
While the following doesn't:
let map f xs =
let rec map xs =
cont {
match xs with
| [] -> return []
| x :: xs ->
let! v = fun g -> g(f x)
let! xs = map xs
return v :: xs
}
map xs id;;
let q = [1..100000] |> map ((+) 1)
To fix your example, add this method to your definition of the monad:
member this.Delay(mk) = fun c -> mk () c
Apparently the part that overflows is the destruction of the large input list in the recursive call of map. Delaying it solves the problem.
Note that your second version puts the recursive call to map behind another let! which desugars to Bind and an extra lambda, in effect delaying the recursive call to map.
I had to pursue a few false trails before reaching this conclusion. What helped was observing that StackOverflow is thrown by OCaml as well (albeit at a higher N) unless the recursive call is delayed. While F# TCO has some quirks, OCaml is more proven, so this convinced me that the problem is indeed with the code and not the compiler:
let cReturn x = fun k -> k x
let cBind m f = fun c -> m (fun a -> f a c)
let map f xs =
(* inner map loop overflows trying to pattern-match long lists *)
let rec map xs =
match xs with
| [] -> cReturn []
| x :: xs ->
cBind (map xs) (fun xs -> cReturn (f x :: xs)) in
map xs (fun x -> x)
let map_fixed f xs =
(* works without overflowing by delaying the recursive call *)
let rec map xs =
match xs with
| [] -> cReturn []
| x :: xs ->
cBind (fun c -> map xs c) (fun xs -> cReturn (f x :: xs)) in
map xs (fun x -> x)
let map_fused f xs =
(* manually fused version avoids the problem by tail-calling `map` *)
let rec map xs k =
match xs with
| [] -> k []
| x :: xs ->
map xs (fun xs -> k (f x :: xs)) in
map xs (fun x -> x)
The F# compiler is sometimes not very clever - in the first case it computes map xs then f x and then joins them, so map xs is not in a tail position. In the second case, it can reorder the map xs to be in tail position easily.