I am trying to get the number of elements in the set, I am getting errors while compiling the following code, can someone please help me fix it:
let rec size S =
match S with
|[] -> false
|e::rest -> (e = S) size S.length rest
I was able to figure it out by using head and tail coordination as follows:
let rec size S =
match S with
|[] -> 0
|head::tail -> size tail + 1
Related
While doing practice, I build a simple function that returns the biggest value in a list:
let rec findMax = // Find maximum value in list
fun l ->
let rec aux =
fun l k ->
match l with
| [] -> k
| x::xs -> if x >= k then aux xs x
else aux xs k
aux l 0
Meanwhile, I built a similar function to find the smallest element in a list:
let finMin = //Find smallest value in list
fun l ->
let rec aux =
fun l k ->
match l with
| [] -> k
| x::xs -> if x <= k then aux xs x
else aux xs k
aux l 0
Here the problem: I initialized both aux functions with k = 0. It is only partially fine: findMax works properly as long as no negative values are in the list. Similarly, findMin works well only with negative numbers.
What should be the proper value to efficiently initialize k? Is there a system-dependant value? Should i previously calculate it? Am I approaching the problem from the wrong side?
P.S. I do not use library functions to find min and max because I am learning the mechanics of the language. Thanks for your patience.
You can take the first item in the list to be the min or max value and then recurse down the rest of the list comparing as you are going. For example:
let myMax items =
match items with
| [] -> failwith "no data"
| head :: tail ->
let rec recMax maxSoFar items =
match items with
| [] -> maxSoFar
| head :: tail ->
if head > maxSoFar then
recMax head tail
else
recMax maxSoFar tail
recMax head tail
It should be System.Int32.MaxValue but also note you should use System.Int32.MinValue for findMax in order to make it work properly with negatives.
i want to use the functional way to count this and i want to count them efficiently so i do not want to store the sequence, just go through it and count the numbers
let conjv2 x =
let next n = match n%2 with
|0 -> n/2
|_ -> n*3+1
Seq.initInfinite next
|> Seq.takeWhile(fun n -> n > 1)
|> Seq.length
this does not work and returns 0 for any positive number, it is the 3n+1 conjecture and i am finding it really hard to count them efficiently, this code works fine but i want to do it the functional way :
let conj x =
let mutable ansa = x
let mutable cycles = 1
while ansa > 1 do
cycles <- cycles+1
ansa <- match ansa%2 with
|0 -> ansa/2
|_ -> ansa*3+1
cycles
The key problem with the sample is that you're using Seq.initInfinite instead of Seq.unfold.
Seq.initInfinite calls the specified function with the index of the element as argument (0, 1, 2, ..)
Seq.unfold calls the specified function with the state generated by the previous iteration
Note that your code also does not use the argument x and so your function ends up being 'a -> int rather than int -> int which is what you'd expect - this is a good indication that there is something wrong!
To fix this, try something like this:
let conjv2 x =
let next n = match n%2 with
|0 -> n/2
|_ -> n*3+1
Seq.unfold (fun st -> let n = next st in Some(n, n)) x
|> Seq.takeWhile(fun n -> n > 1)
|> Seq.map (fun v -> printfn "%A" v; v)
|> Seq.length
The function passed to unfold needs to return an option with the new state & a value to emit. To generate infinite sequence, we always return Some and the emitted values are the intermediate states.
This returns values that are smaller by 2 than your original conj, because conj starts with 1 (rather than 0) and it also counts the last value (while here, we stop before ansa=1). So you'll need to add 2 to the result.
I'm trying to solve tasks from 99 Haskell problems in F#.
The task #7 looks pretty simple, and the solution can be found in lots of places. Except the fact that the first several solutions that I've tried and found by googling (e.g. https://github.com/paks/99-FSharp-Problems/blob/master/P01to10/Solutions.fs) are wrong.
My example is pretty simple.
I'm trying to build extremely deep nested structure and fold it
type NestedList<'a> =
| Elem of 'a
| NestedList of NestedList<'a> list
let flatten list =
//
(* StackOverflowException
| Elem(a) as i -> [a]
| NestedList(nest) -> nest |> Seq.map myFlatten |> List.concat
*)
// Both are failed with stackoverflowexception too https://github.com/paks/99-FSharp-Problems/blob/master/P01to10/Solutions.fs
let insideGen count =
let rec insideGen' count agg =
match count with
| 0 -> agg
| _ ->
insideGen' (count-1) (NestedList([Elem(count); agg]))
insideGen' count (Elem(-1))
let z = insideGen 50000
let res = flatten z
I've tried to rewrite solution in CPS style, but eiter I'm doing something wrong or look into incorrect direction - everything that I've tried isn't working.
Any advices?
p.s. Haskell solution, at least on nested structure with 50000 nested levels is working slowly, but without stack overflow.
Here's a CPS version that doesn't overflow using your test.
let flatten lst =
let rec loop k = function
| [] -> k []
| (Elem x)::tl -> loop (fun ys -> k (x::ys)) tl
| (NestedList xs)::tl -> loop (fun ys -> loop (fun zs -> k (zs # ys)) xs) tl
loop id [lst]
EDIT
A much more readable way to write this would be:
let flatten lst =
let results = ResizeArray()
let rec loop = function
| [] -> ()
| h::tl ->
match h with
| Elem x -> results.Add(x)
| NestedList xs -> loop xs
loop tl
loop [lst]
List.ofSeq results
Disclaimer - I'm not a deep F# programmer and this will not be idiomatic.
If your stack is overflowing, it means that you don't have a tail recursive solution. It also means that you are choosing to use stack memory for state. Traditionally, you want to exchange heap memory for stack memory since heap memory is in comparatively large supply. So the trick is to model a stack.
I'm going to define a virtual machine that is a stack. Each stack element will be a state nugget for traversing a list which will include the list and a program counter, which is the current element to examine and will be a tuple of a NestedList<'a> list * int. The list is the current list being traversed. The int is the current position in the list.
type NestedList<'a> =
| Elem of 'a
| Nested of NestedList<'a> list
let flatten l =
let rec listMachine instructions result =
match instructions with
| [] -> result
| (currList, currPC) :: tail ->
if currPC >= List.length currList then listMachine tail result
else
match List.nth currList currPC with
| Elem(a) -> listMachine ((currList, currPC + 1 ) :: tail) (result # [ a ])
| Nested(l) -> listMachine ((l, 0) :: (currList, currPC + 1) :: instructions.Tail) result
match l with
| Elem(a) -> [ a ]
| Nested(ll) -> listMachine [ (ll, 0) ] []
What have I done? I've written a tail-recursive function that operates of "Little Lisper" style code - if my instruction list is empty, return my accumulated result. If not, operate on the top of the stack. I bind a convenience variable to the top and if the PC is at the end, I recurse on the tail of the stack (pop) with the current result. Otherwise, I look at the current element in the list. If it's an Elem, I recurse, advancing the PC and appending the Elem onto the list. If it's not an elem, I recurse, by pushing a new stack with the NestedList followed by the current stack elem with the PC advanced by 1 and everything else.
I tried doing a tail recursive function that will count the elements of a list, followed the rules, used an acumulator, but when I run it like this:
lstcountr [1..98765432];;
I get this:
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
this is my function (which I thought is tail recursive /efficient):
let lstcountr ls =
let rec loop ls total =
match ls with
| [] -> total
| hd::tl -> loop tl total+1I
loop ls 0I
can this be done better ?
You function isn't tail recursive.
| hd::tl -> loop tl total+1I
Should be
| hd::tl -> loop tl (total+1I)
Operators are interpreted after function calls, normally you can't tell in situations like this because the results are identical, but that is not true with tail recursion.
Also as Tejs said, you are creating a list of too many items which is causing your OutOfMemoryException. Have you tried using a seq { }?
Too much recursion would mean you get a StackOverflowException, not an OutOfMemoryException - This is because you're trying to create a list of 98765432 elements at once.
Regardless of your recursion, this list passed as the argument is created in memory, not lazily I might add.
Here are two ways of writing a sequence-based version that's polymorphic in its return type:
module Seq =
open LanguagePrimitives
let inline count items = Seq.fold (fun i _ -> i + GenericOne) GenericZero items
//faster
let inline count (items: seq<_>) =
use e = items.GetEnumerator()
let rec loop n =
if e.MoveNext() then loop (n + GenericOne)
else n
loop GenericZero
This allows you to compute length using the the most suitable type:
let n : bigint = Seq.count {1I .. 987298234982374923847I}
let n : float = Seq.count {1I .. 987298234982374923847I}
I recently started solving Project Euler problems in Scala, however when I got to problem 14, I got the StackOverflowError, so I rewrote my solution in F#, since (I am told) the F# compiler, unlike Scala's (which produces Java bytecode), translates recursive calls into loops.
My question to you therefore is, how is it possible that the code below throws the StackOverflowException after reaching some number above 113000? I think that the recursion doesn't have to be a tail recursion in order to be translated/optimized, does it?
I tried several rewrites of my code, but without success. I really don't want to have to write the code in imperative style using loops, and I don't think I could turn the len function to be tail-recursive, even if that was the problem preventing it from being optimized.
module Problem14 =
let lenMap = Dictionary<'int,'int>()
let next n =
if n % 2 = 0 then n/2
else 3*n+1
let memoize(num:int, lng:int):int =
lenMap.[num]<-lng
lng
let rec len(num:int):int =
match num with
| 1 -> 1
| _ when lenMap.ContainsKey(num) -> lenMap.[num]
| _ -> memoize(num, 1+(len (next num)))
let cand = seq{ for i in 999999 .. -1 .. 1 -> i}
let tuples = cand |> Seq.map(fun n -> (n, len(n)))
let Result = tuples |> Seq.maxBy(fun n -> snd n) |> fst
NOTE: I am aware that the code below is very far from optimal and several lines could be a lot simpler, but I am not very proficient in F# and did not bother looking up ways to simplify it and make it more elegant (yet).
Thank you.
Your current code runs without error and gets the correct result if I change all the int to int64 and append an L after every numeric literal (e.g. -1L). If the actual problem is that you're overflowing a 32-bit integer, I'm not sure why you get a StackOverflowException.
module Problem14 =
let lenMap = System.Collections.Generic.Dictionary<_,_>()
let next n =
if n % 2L = 0L then n/2L
else 3L*n+1L
let memoize(num, lng) =
lenMap.[num]<-lng
lng
let rec len num =
match num with
| 1L -> 1L
| _ when lenMap.ContainsKey(num) -> lenMap.[num]
| _ -> memoize(num, 1L+(len (next num)))
let cand = seq{ for i in 999999L .. -1L .. 1L -> i}
let tuples = cand |> Seq.map(fun n -> (n, len(n)))
let Result = tuples |> Seq.maxBy(fun n -> snd n) |> fst