I'm trying to reverse an integer in F#. I have the following approach:
//let the number be n
rev = 0
while(n != 0){
rev = rev * 10 + n % 10;
n /= 10;
}
// rev now contains the reverse integer of n
I'm new to F#, and I don't know the the idiomatic syntax to achieve this implementation. I don't want to reverse the number by converting it to string first. How can this implementation be done in F# in an idiomatic way?
Create a recursive inner function that you call like so.
let reverse n =
let rec revInner n rev =
match n with
| 0 -> rev
| _ -> revInner (n / 10) (rev * 10 + n % 10)
revInner n 0
reverse 43221 // -> 12234
Whenever you have imperative loops such as a while look to convert it to a recursive function. In this case you need an inner function that is recursively called. The first pattern match deals with the termination condition of the while, the second deals with the core whileexecution:
let revNum number =
let rec loop rev = function
| 0 -> rev
| fwd -> loop (rev*10 + fwd%10) (fwd/10)
loop 0 number;;
Related
I'm trying to concatenate a string with a certain amount of times, but I feel like I've cheated a bit (or at least not actually understood how it's supposed to be done) by using a higher-order function:
let repeat s n =
String.replicate n s |> printfn "%s"
repeat "a" 10
Obviously gives me "aaaaaaaaaa", but how could I do this without a higher-order function? I feel like it's a very simple problem but I can't seem to wrap my head around it, the F# syntax, or way of thinking, is still troublesome for me.
If you just want a recursive solution, how about this?
let rec repeat s n =
match n with
| _ when n <= 0 -> ""
| _ -> s + (repeat s (n-1))
repeat "a" 10
or in a more "classic" style with an if-expression:
let rec repeat s n =
if n <= 0 then
""
else
s + (repeat s (n-1))
repeat "a" 10
And here's one way using list comprehension and fold, which is the go to function for recursion:
[for i in 1..10 -> "a"] |> List.fold (+) ""
Tail Recursive version
let repeat2 s n =
let rec loop acc n =
match n with
| _ when n > 0 -> loop (acc + s) (n - 1)
| _ -> acc
loop "" n
repeat "oijdfsaoijdoyasjd" 100000 // Process is terminated due to StackOverflowException.
[for i in 1..100000 -> "oijdfsaoijdoyasjd"] |> List.fold (+) "" // no stack overflow
repeat2 "oijdfsaoijdoyasjd" 100000 // no stack overflow
But prepared for massive amounts of gen2 GC and a few min. of runtime.
I created my own datatype And I'm trying to create the sum of all the numbers in that datatype which is a list of lists. I don't want to use any F# libraries
My datatype
type elist = A | L of int * elist
I'm a beginner in F# and trying to grasp my head on it. I want to do this recursively. My thinking going into it is to traverse to the end of the list and start an sum and go back to the front and add each one.
example:
let l = L(4, L(3, L(6, L(3, A))))
that should return
val it : int 16
Here's my code and I know it is wrong:
let rec sum l =
let a = 0
match l with
| A -> 0
| L(head,A) -> head
| L(head,tail) -> sum tail + a
You're nearly there. All you need is to lose the a:
let rec sum l =
match l with
| A -> 0
| L(head,A) -> head
| L(head,tail) -> head + sum tail
Then evaluating sum l when l = L(4, L(3, L(6, L(3, A)))) gives
val it : int = 16
as required.
I'm messing around with F# and Fable, and trying to test my understanding. To do so, I tried creating a function to calculate e given a certain number of iterations. What I've come up with is
let eCalc n =
let rec internalECalc ifact sum count =
match count = n with
| true -> sum
| _ -> internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
Which works fine, returning 2.7182818284590455 when called with
eCalc 20
However, if I try using, what I think is, the more correct form
let eCalc n =
let rec internalECalc ifact sum count =
match count with
| n -> sum
| _ -> internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
I get a warning "[WARNING] This rule will never be matched (L5,10-L5,11)", and returned value of 0. (and the same thing happens if I swap 'n' and 'count' in the match statement). Is there a reason I can't use 'n' in the match statement? Is there a way around this so I can use 'n'?
Thanks
When you use a name in a match statement, you're not checking it against the value assigned to that variable the way you think you are. You are instead assigning that name. I.e.,
match someInt with
| n -> printfn "%d" n
will print the value of someInt. It's the equivalent of let n = someInt; printfn "%d" n.
What you wanted to do was use a when clause; inside a when clause, you're not pattern-matching, but doing a "standard" if check. So what you wanted was:
let eCalc n =
let rec internalECalc ifact sum count =
match count with
| cnt when cnt = n -> sum
| _ -> internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
Does that make sense, or do you need me to go into more detail?
P.S. In a case like this one where your match function looks like "x when (boolean condition involving x) -> case 1 | _ -> case 2", it's quite a bit more readable to use a simple if expression:
let eCalc n =
let rec internalECalc ifact sum count =
if count = n then
sum
else
internalECalc (ifact / (float count)) (sum + ifact) (count+1)
internalECalc 1.0 0.0 1
I'm trying to create an infinite Stream in F# that contains armstrong numbers. An armstrong number is one whose cubes of its digits add up to the number. For example, 153 is an armstrong number because 1^3 + 5^3 + 3^3 = 153. so far, I have created several functions to help me do so. They are:
type 'a stream = Cons of 'a * (unit -> 'a stream);;
let rec upfrom n = Cons (n, fun() -> upfrom (n+1));;
let rec toIntArray = function
| 0 -> []
| n -> n % 10 :: toIntArray (n / 10);;
let rec makearmstrong = function
| [] -> 0
| y::ys -> (y * y * y) + makearmstrong ys;;
let checkarmstrong n = n = makearmstrong(toIntArray n);;
let rec take n (Cons(x,xsf)) =
match n with
| 0 -> []
| _ -> x :: take (n-1)(xsf());;
let rec filter p (Cons (x, xsf)) =
if p x then Cons (x, fun() -> filter p (xsf()))
else filter p (xsf());;
And finally:
let armstrongs = filter (fun n -> checkarmstrong n)(upfrom 1);;
Now, when I do take 4 armstrongs;;, (or any number less than 4) this works perfectly and gives me [1;153;370;371] but if I do take 5 armstrongs;;nothing happens, it seems like the program freezes.
I believe the issue is that there are no numbers after 407 that are the sums of their cubes (see http://oeis.org/A046197), but when your code evaluates the equivalent of take 1 (Cons(407, filter checkarmstrong (upfrom 408))) it's going to force the evaluation of the tail and filter will recurse forever, never finding a matching next element. Also note that your definition of Armstrong numbers differs from, say, Wikipedia's, which states that the power the digits are raised to should be the number of digits in the number.
I'm trying to build the nth power function in F#. (Yes, there's already Math.Pow in .Net). Here is my attempt:
let rec nthPower x n =
match n with
| 0 -> 1
| _ -> x * (nthPower x (n-1))
This works fine when n >= 0; however, I don't know how to handle the negative case: when n < 0.
Question:
How to handle the negative case? (n<0)
Is this recursive algorithm efficient? or are there any efficient ways in F#?
You can implement it like this:
let rec nthPower x n =
match n with
| 0 -> 1m
| t when t < 0 -> 1m / (nthPower x -n)
| _ -> decimal x * (nthPower x (n - 1));;
The t when t < 0 allows the pattern matching to match a range of values. I would say that the RHS of this line is self-explanatory, but let me know if it's unclear.
Regarding question #2, I don't think there's anything particularly inefficient about this approach and there's probably not a much simpler way to do it. I'm not sure what the most efficient approach is, but hopefully some mathematicians can chime in.
Edit: I have found an approach that is more efficient for exponents > ~10. It uses memoization and divide-and-conquer to compute the result in O(log n) time instead of O(n):
let rec nthPower x n =
match n with
| 0 -> 1.0
| 1 -> double x
| t when t < 0 -> 1.0 / (nthPower x -n)
| _ ->
let p = nthPower x (n / 2)
p * p * nthPower x (n % 2)