Hi i have some difficulty in understanding tail-recursivity. I know thats it's important to avoid infinite loops and also for memory usage. I've seen some examples on simple functions like Fibonacci in "Expert in F#", but I don't think i've seen code when the result is something different than just a number.
What would be the accumulator then ? i'm not sure...
Here is a recursive function that I've written. It counts the number of inversions in an array, using the quicksort algorithm. [it's taken from an exercise of the Coursera MOOC Algo I by Stanford]
I'd be grateful if somebody could explain how to make that tail recursive.
[Also, i've translated that code from imperative code, as i had written that in R before, so the style is not functional at all...]
another question: is the syntax correct, A being a (mutable) array, i've written let A = .... everywhere ?
is A <- .... better / the same ?
open System.IO
open System
let X = [|57; 97; 17; 31; 54; 98; 87; 27; 89; 81; 18; 70; 3; 34; 63; 100; 46; 30; 99;
10; 33; 65; 96; 38; 48; 80; 95; 6; 16; 19; 56; 61; 1; 47; 12; 73; 49; 41;
37; 40; 59; 67; 93; 26; 75; 44; 58; 66; 8; 55; 94; 74; 83; 7; 15; 86; 42;
50; 5; 22; 90; 13; 69; 53; 43; 24; 92; 51; 23; 39; 78; 85; 4; 25; 52; 36;
60; 68; 9; 64; 79; 14; 45; 2; 77; 84; 11; 71; 35; 72; 28; 76; 82; 88; 32;
21; 20; 91; 62; 29|]
// not tail recursive. answer = 488
let N = X.Length
let mutable count = 0
let swap (A:int[]) a b =
let tmp = A.[a]
A.[a] <- A.[b]
A.[b] <- tmp
A
let rec quicksortNT (A:int[]) =
let L = A.Length
match L with
| 1 -> A
| 2 -> count <- count + 1
if (A.[0]<A.[1]) then A
else [|A.[1];A.[0]|]
| x -> let p = x
let pval = A.[p-1]
let A = swap A 0 (p-1)
let mutable i = 1
for j in 1 .. (x-1) do
if (A.[j]<pval) then let A = swap A i j
i <- i+1
// end of for loop
// putting back pivot at its right place
let A = swap A 0 (i-1)
let l1 = i-1
let l2 = x-i
if (l1=0) then
let A = Array.append [|A.[0]|] (quicksortNT A.[1..p-1])
count <- count + (l2-1)
A
elif (l2=0) then
let A = Array.append (quicksortNT A.[0..p-2]) [|A.[p-1]|]
count <- count + (l2-1)
A
else
let A = Array.append ( Array.append (quicksortNT A.[0..(i-2)]) [|A.[i-1]|] ) (quicksortNT A.[i..p-1])
count <- count + (l1-1)+(l2-1)
A
let Y = quicksortNT X
for i in 1..N do printfn "%d" Y.[i-1]
printfn "count = %d" count
Console.ReadKey() |> ignore
Thank you very much for your help
As I said in my comment: you do inplace-swapping so it makes no sense to recreate and return arrays.
But as you ask about tail-recursive solutions look at this version using lists and continuation-passing-style to make the algorithm tail-recursive:
let quicksort values =
let rec qsort xs cont =
match xs with
| [] -> cont xs
| (x::xs) ->
let lower = List.filter (fun y -> y <= x) xs
let upper = List.filter (fun y -> y > x) xs
qsort lower (fun lowerSorted ->
qsort upper (fun upperSorted -> cont (lowerSorted # x :: upperSorted)))
qsort values id
remarks:
you can think of it like this:
first partition the input into upper and lower parts
then start with sorting (recursively) the lower part, when you are done with this continue by...
... take lowerSorted and sort the upper part as well and continue with ...
... take both sorted parts, join them and pass them to the outer continuation
the outermost continuation should of course just be the id function
some will argue that this is not quicksort as it does not sort inplace!
maybe it's hard to see but it's tail-recursive as the very last call is to qsort and it's result will be the result of the current call
I used List because the pattern-matching is so much nicer - but you can adopt this to your version with arrays as well
in those cases (as here) where you have multiple recursive calls I always find cont-passing solutions to be easier to write and more natural - but accumulators could be used as well (but it will get messy as you need to pass where you are too)
this will not take less memory than the version without the cont-passing at all - it just will be placed on the heap instead of the stack (you usually have way more heap available ;) ) - so it's a bit like cheating
that's why the imperative algorithm is still way better performance-wise - so a usual compromise is to (for example) copy the array, use the inplace-algorithm on the copy and then return the copy - this way the algorithm behaves as if it's pure on the outside
The whole point to quicksort's swapping partition procedure is that it can mutate the same array; you just pass it the low and the high index of the array's range it has to process.
So make a nested function and pass it just the 2 indices. To make it tail recursive, add the third parameter, list-of-ranges-to-process; when that becomes empty, you're done. Wikibook says you mutate arrays with A.[i] <- A.[j].
A nested function can access its parent function's argument directly, because it is in scope. So, make swap nested too:
let rec quicksort (A:int[]) =
let swap a b =
let tmp = A.[a]
A.[a] <- A.[b]
A.[b] <- tmp
let todo = ... (* empty list *)
let rec partition low high =
.... (* run the swapping loop,
find the two new pairs of indices,
put one into TODO and call *)
partition new_low new_high
let L = A.Length
match L with
| 1 -> (* do nothing A *)
| 2 -> count <- count + 1
if (A.[0]<A.[1]) then (* do nothing A *)
else (* [|A.[1];A.[0]|] *) swap 1 0
| x -> ....
partition 0 L
So partition will be tail recursive, working inside the environment set up for it by quicksort.
(disclaimer: I don't know F# and have never used it, but I know Haskell and Scheme, to some degree).
Related
We have to program the knapsack problem in for a school project in different programming types. One is functional programming and I am trying it in F#.
I am using a recursive function to always get the items with the highest value to put into my knapsack. At the end I want to have the highest total value of all elements combined. Here is the solution in Python and I just hoped I could transfer it to F#.
let names = ["Zahnbürste","Zahnpasta", "Teller", "Duschgel", "Shampoo", "Handtuch", "Besteck", "Trinkflasche", "Becher", "Taschenlampe", "Sonnenschutz", "Medikamente"]
let volumes = [2,4,5,2,2.5,10,5,3,3,9,2,1]
let values = [3,19,17,15,13,3,2,8,5,6,17,15]
maxVol = 20;
def rucksackProblem(restVol, i) :
if (i < (len(volumes))) :
dontPack = rucksackProblem(restVol, i + 1)
pack = 0
if (restVol - volumes[i] >= 0) :
pack = values[i] + rucksackProblem(restVol - volumes[i], i + 1)
if (dontPack > pack) :
return dontPack
else :
return pack
else :
return 0
result = rucksackProblem(maxVol, 0)
print(result)
This is what I tried in F#. Please help me figuring out my problems. I am new to F# and functional programming and other solutions to the knapsack problem with hundreds of code lines seem overcomplicated. This doesn´t really print the end result I want to get from this function. It just returns 0:
open System
let names_list = ["Zahnbürste";"Zahnpasta"; "Teller"; "Duschgel";"Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher";"Taschenlampe";"Sonnenschutz";"Medikamente"]
let volumes_list = [2;4;5;2;3;10;5;3;3;9;2;1]
let values_list = [3;19;17;15;13;3;2;8;5;6;17;15]
let maxVolume = 20
let rec rucksackProblem (restVol : int, i : int) =
if i < volumes_list.Length then
let dontPack = rucksackProblem(restVol, i + 1)
let pack = 0
let currentVolumeItem = volumes_list.Item(i)
if restVol - volumes_list.Item(i) >= 0 then
let mutable pack = values_list.Item(i) + rucksackProblem(restVol - volumes_list.Item(i), i + 1)
printf "%i" (volumes_list.Item(i))
else()
if dontPack > pack then
dontPack
else
pack
else
0
let result = rucksackProblem(maxVolume, 0)
printfn "%i" result
Console.ReadKey() |> ignore
I took the liberty to rewrite your code and I ended up with this.
let names = ["Zahnbürste"; "Zahnpasta"; "Teller"; "Duschgel"; "Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher"; "Taschenlampe"; "Sonnenschutz"; "Medikamente"]
let weights = [2; 4; 5; 2; 3; 10; 5; 3; 3; 9; 2; 1]
let profits = [3; 19; 17; 15; 13; 3; 2; 8; 5; 6; 17; 15]
let cap = 20
type Product = { Name: string; Profit: int; Weight: int }
let knappsack names profits weights cap =
let sortItemsInDecreasingOrder =
List.zip3 names profits weights
|> List.map (fun x -> { Name=x.Item1; Profit=x.Item2; Weight=x.Item3 })
|> List.sortBy (fun p -> p.Profit / p.Weight)
|> List.rev
let products = sortItemsInDecreasingOrder
let rec pack bag totalWeight idx =
if idx > List.length names - 1 then bag
else
let p = products.[idx]
if (totalWeight + p.Weight) > cap then bag
else
pack (bag # [p]) (totalWeight + p.Weight) (idx + 1)
pack List.empty 0 1
knappsack names profits weights cap
|> Dump
|> ignore
The result I get is
Name Profit Weight
Sonnenschutz 17 2
Duschgel 15 2
Shampoo 13 3
Zahnpasta 19 4
Teller 17 5
Trinkflasche 8 3
89 19
Btw. if you are interested in learning functional programming using f# I can highly recommend https://fsharpforfunandprofit.com/.
I can't vouch for the correctness or efficiency of the algorithm but this should do what you're looking for:
open System
let names_list = ["Zahnbürste";"Zahnpasta"; "Teller"; "Duschgel";"Shampoo"; "Handtuch"; "Besteck"; "Trinkflasche"; "Becher";"Taschenlampe";"Sonnenschutz";"Medikamente"]
let volumes_list = [2;4;5;2;3;10;5;3;3;9;2;1]
let values_list = [3;19;17;15;13;3;2;8;5;6;17;15]
let maxVolume = 20
let rec rucksackProblem (restVol : int) (i : int) =
if i < volumes_list.Length then
let dontPack = rucksackProblem restVol (i + 1)
let currentVolumeItem = volumes_list.[i]
let pack =
if restVol - volumes_list.[i] >= 0 then
values_list.[i] + rucksackProblem (restVol - volumes_list.[i]) (i + 1)
else 0
if dontPack > pack then
dontPack
else
pack
else
0
let result = rucksackProblem maxVolume 0
printfn "%i" result
Note that because your mutable pack was defined inside of the scope of an if it was inaccessible outside that branch of the if. I moved that definition above so it could be accessed outside.
I also did a few other changes. In F# items in a list can be accessed as list.[index]. Parameters are passed separated by spaces not commas as this is a more flexible approach, for example allows currying.
i am trying to implement a recursive function which takes a float and returns a list of ints representing the continued fraction representation of the float (https://en.wikipedia.org/wiki/Continued_fraction) In general i think i understand how the algorithm is supposed to work. its fairly simply. What i have so far is this:
let rec float2cfrac (x : float) : int list =
let q = int x
let r = x - (float q)
if r = 0.0 then
[]
else
q :: (float2cfrac (1.0 / r ))
the problem is with the base case obviously. It seems the value r never does reduce to 0.0 instead the algorithm keeps on returning values which are the likes of 0.0.....[number]. I am just not sure how to perform the comparison. How exactly should i go about it. The algorithm the function is based on says the base case is 0, so i naturally interpret this as 0.0. I dont see any other way. Also, do note that this is for an assignment where i am explicitly asked to implement the algorithm recursively. Does anyone have some guidance for me? It would be much appreciated
It seems the value r never does reduce to 0.0 instead the algorithm keeps on returning values which are the likes of 0.0.....[number].
This is a classic issue with floating point comparisons. You need to use some epsilon tolerance value for comparisons, because r will never reach exactly 0.0:
let epsilon = 0.0000000001
let rec float2cfrac (x : float) : int list =
let q = int x
let r = x - (float q)
if r < epsilon then
[]
else
q :: (float2cfrac (1.0 / r))
> float2cfrac 4.23
val it : int list = [4; 4; 2; 1]
See this MSDN documentation for more.
You could define a helper function for this:
let withinTolerance (x: float) (y: float) e =
System.Math.Abs(x - y) < e
Also note your original solution isn't tail-recursive, so it consumes stack as it recurses and could overflow the stack. You could refactor it such that a float can be unfolded without recursion:
let float2cfrac (x: float) =
let q = int x
let r = x - (float q)
if withinTolerance r 0.0 epsilon then None
else Some (q, (1.0 / r))
4.23 |> Seq.unfold float2cfrac // seq [4; 4; 2; 1]
I am practicing on matrix at the moment but I am not really sure on the most efficient way to resolve some of the problems I encounter.
My first "problem" is to optimize a function. What I try to do is to iterate trough the 'a matrix which is a 'a array array.
For each line identified by an integer between 0 and 4 (the matrix has a size of (5,10)), I count how many "one" there is.
I had to split it in three different functions but I was wondering if there is any more optimized way to solve this problem ?
let count m i =
let ret=Array.fold_left (fun x y -> if y=1 then x+1 else x) 0 (m.(i)) in
ret;;
let rec clear l =
match l with
|[]->[]
|(a,b)::[]->if b=0 then [] else (a,b)::[]
|(a,b)::c->if b=0 then clear c else (a,b)::clear c;;
let all_moves s =
match s with
|(a,_)->clear[(0,count a 0);(1,count a 1);(2,count a 2);(3,count a 3);(4,count a 4)];;
Second of all, my main problem is to iterate through the entire matrix at once.
I'm trying to count all the 1 in the matrix except for the line identified by param "i".
I tried several things but I'm really stuck at the moment.
let countall m i =
let ret=Array.fold_left (fun x y -> if pos != i then x + y else ())
(Array.fold_left (fun x y -> if y=1 then x+1 else x) 0 (m.(i)))
0 m in
ret;;
I would like to thank you in advance for your help and I thought I might give a matrix for you to test my functions:
let c = [|[|1; 1; 1; 1; 1; 0; 0; 0; 0; 0|]; [|1; 1; 1; 1; 1; 1; 1; 1; 0; 0|];
[|1; 1; 1; 1; 1; 1; 1; 1; 1; 0|]; [|1; 0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|1; 1; 1; 1; 1; 1; 1; 1; 1; 1|]|]
Sincerely yours,
Rama
Some pointers:
Expressions of the form let ret = expr in ret can be simplified to expr. And the reverse application operator |> can often be used to elide trivial let expressions.
If a function starts with a match expression that has just a single clause, that clause can often be rolled into the function signature. E.g. let all_moves s = match s with (a, _) -> ... becomes `let all_moves (a, _) = ...'.
The Array and List modules have more than just fold functions (and alternative standard libraries, such as Core, Batteries, or ExtLib add more functionality to them) that can be used to simplify a lot of Array/List processing.
Example:
let count_ones row =
Array.fold_left (fun c x -> if x=1 then c+1 else c) 0 row
let all_moves (mat, _) =
Array.mapi (fun i row -> (i, count_ones row)) mat
|> Array.to_list |> List.filter (fun (_, c) -> c != 0)
I'm not 100% sure what the intended semantics of countall are, but if I'm understanding it correctly, the following should work (it follows the basic structure of your attempted solution, but relies on mapi instead of fold_left, which is a better fit):
let countall mat k =
Array.mapi (fun i row -> if i = k then 0 else count_ones row) mat
|> Array.fold_left (+) 0
This function can be implemented in different ways, too, e.g.:
let countall mat k =
Array.(append (sub mat 0 k) (sub mat (k+1) (length mat - k - 1)))
|> Array.map count_ones |> Array.fold_left (+) 0
In this variant, I'm using a local open Array.(expr) so that I don't have to prefix every single array operation with Array.. Also, in both versions (+) is a way to write the plus operator as a function with two arguments, and is roughly equivalent to writing (fun x y -> x + y) in its place.
Maybe that could help you
let countall m i =
snd (
Array.fold_left (fun (lg,c) v ->
let c=
if lg = i then c
else
Array.fold_left (fun c xy -> if xy=1 then c+1 else c) c v
in
(lg+1,c)
) (0,0) m
)
;;
Test
# countall c 0;;
- : int = 28
I'm sure there's a way to do this elegantly in SML but I'm having difficulty keeping track of the number of iterations (basically the number of times my function has been called).
I'm trying to write a function that evaluates to a pair of numbers, one for the floor of the answer and the other for the remainder. So if you called:
divmod(11, 2), you'd get (5, 1) back.
Here's what I have so far:
divmod(number : int, divisor : int) =
if number < divisor then
(number, count)
else
divmod(number - divisor, divisor);
Obviously, I haven't set up my count variable so it won't compile but that's the idea of the algorithm. All that's left is initializing count to 0 and being able to pass it between recursive calls. But I'm only allowed the two parameters for this function.
I can, however, write auxiliary functions.
Thoughts?
If SML has support for nested functions you could do like this:
divmod(number : int, divisor : int) =
_divmod(n : int, d : int, count : int) =
if n < d then
(count, n)
else
_divmod(n - d, d, count + 1)
_divmod(number, divisor, 0)
Personally, I like the fact that SML isn't a pure functional language. Keeping track of function calls is naturally done via side effects (rather than explicitly passing a counter variable).
For example, given a generic recursive Fibonacci:
fun fib 0 = 0
| fib 1 = 0
| fib n = fib(n-2) + fib(n-1);
You can modify it so that every time it is called it increments a counter as a side effect:
counter = ref 0;
fun fib 0 = (counter := !counter + 1; 0)
| fib 1 = (counter := !counter + 1; 1)
| fib n = (counter := !counter + 1; fib(n-2) + fib(n-1));
You can use this directly or wrap it up a bit:
fun fibonacci n = (
counter :=0;
let val v = fib n
in
(!counter,v)
end);
With a typical run:
- fibonacci 30;
val it = (2692537,832040) : int * int
(Which, by the way, shows why this version of the Fibonacci recursion isn't very good!)
Update: I can't use any List.function stuff.
I'm new to OCaml and I'm learning this course in which I'm supposed to calculate a list of non decreasing values from a list of values.
So for e.g. I have a list [1; 2; 3; 1; 2; 7; 6]
So function mono that takes in a list returns the following:
# mono [1; 2; 3; 1; 2; 7; 6];;
- : int list = [1; 2; 3; 7]
I do the following:
let rec calculateCheck value lst = (
match lst with
[] -> true
| x :: xs -> (
if (value < x) then
false
else
calculateCheck value xs
)
);;
let rec reverse_list lst = (
match lst with
[] -> []
| x :: xs -> (
reverse_list xs # [x]
)
);;
let shouldReverse = ref 1;;
let cancelReverse somelist lst = (
shouldReverse := 0;
reverse_list lst
);;
let rec mono lst = (
let somelist = ref lst in
if (!shouldReverse = 1) then
somelist := cancelReverse somelist lst
else
somelist := lst;
match !somelist with
[] -> []
| x :: xs -> (
if (calculateCheck x xs) then
[x] # mono xs
else
[] # mono xs
);
);;
Problem?
This only works once because of shouldReverse.
I cannot reverse the value; mono list should return non decreasing list.
Question?
Any easy way to do this?
Specifically how to get a subset of the list. For e.g. for [1; 2; 3; 5; 6], I want [1; 2; 3] as an output for 5 so that I can solve this issue recursively. The other thing, is you can have a list as [1; 2; 3; 5; 6; 5]:: so for the second 5, the output should be [1; 2; 3; 5; 6].
Any ideas?
Thanks
A good way to approach this kind of problem is to force yourself to
formulate what you're looking for formally, in a mathematically
correct way. With some training, this will usually get you
a description that is close to the final program you will write.
We are trying to define a function incr li that contains the
a strictly increasing subsequence of li. As Jeffrey Scoffield asked,
you may be looking for the
longest
such subsequence: this is an interesting and non-trivial algorithmic
problem that is well-studied, but given that you're a beginner
I suppose your teacher is asking for something simpler. Here is my
suggestion of a simpler specification: you are looking for all the
elements that are greater than all the elements before them in the
list.
A good way to produce mathematical definitions that are easy to turn
into algorithms is reasoning by induction: define a property on
natural numbers P(n) in terms of the predecessor P(n-1), or define
a property on a given list in terms of this property on a list of one
less element. Consider you want to define incr [x1; x2; x3; x4]. You
may express it either in terms of incr [x1; x2; x3] and x4, or in
terms of x1 and incr [x2; x3; x4].
incr [x1;x2;x3;x4] is incr[x1;x2;x3], plus x4 if it is bigger
than all the elements before it in the list, or, equivalently, the
biggest element of incr[x1;x2;x3]
incr [x1;x2;x3;x4] is incr[x2;x3;x4] where all the elements
smaller than x1 have been removed (they're not bigger than all
elements before them), and x1 added
These two precise definitions can of course be generalized to lists of
any length, and they give two different ways to write incr.
(* `incr1` defines `incr [x1;x2;x3;x4]` from `incr [x1;x2;x3]`,
keeping as intermediate values `subli` that corresponds to
`incr [x1;x2;x3]` in reverse order, and `biggest` the biggest
value encountered so far. *)
let incr1 li =
let rec incr subli biggest = function
| [] -> List.rev subli
| h::t ->
if h > biggest
then incr (h::subli) h t
else incr subli biggest t
in
match li with
| [] -> []
| h::t -> incr [h] h t
(* `incr2` defines `incr [x1;x2;x3;x4]` from `incr [x2;x3;x4]`; it
needs no additional parameter as this is just a recursive call on
the tail of the input list. *)
let rec incr2 = function
| [] -> []
| h::t ->
(* to go from `incr [x2;x3;x4]` to `incr [x1;x2;x3;x4]`, one
must remove all the elements of `incr [x2;x3;x4]` that are
smaller than `x1`, then add `x1` to it *)
let rec remove = function
| [] -> []
| h'::t ->
if h >= h' then remove t
else h'::t
in h :: remove (incr2 t)