I am trying to write a binary search in f#, but stumbled at a problem:
let find(words:string[]) (value:string) =
let mutable mid = 0
let mutable fpos = 0
let mutable lpos = words.Length - 1
while fpos < lpos do
mid <- (fpos + lpos) / 2
if value < words.[mid] then
lpos <- mid
else if value > words.[mid] then
fpos <- mid
else if value = words.[mid] then
true
false
It is giving error at the line which says true saying it expected an expression of type unit() instead got bool. What is the correct way to write this function?
Edit:
Temporarily I took to writing as follows:
let find(words:string[]) (value:string) =
let mutable mid = 0
let mutable fpos = 0
let mutable lpos = words.Length - 1
let ret = false
while fpos < lpos && ret = false do
mid <- (fpos + lpos) / 2
if value < words.[mid] then
lpos <- mid
else if value > words.[mid] then
fpos <- mid
else if value = words.[mid] then
ret <- true
ret
But execution wise I think I am doing a lot of operations here than intended...
Use a recursive function:
let find(words:string[]) (value:string) =
let rec findRec fpos lpos =
if fpos > lpos then
false
else
let mid = (fpos + lpos) / 2
if value < words.[mid] then
findRec fpos (mid-1)
else if value > words.[mid] then
findRec (mid+1) lpos
else
true
findRec 0 (words.Length-1)
Non-recursive version (adapted from Gene's answer):
let find (words: string[]) (value:string) =
let mutable mid = 0
let mutable fpos = 0
let mutable lpos = words.Length - 1
let mutable cont = true
while fpos <= lpos && cont do
mid <- (fpos + lpos) / 2
match sign(value.CompareTo(words.[mid])) with
| -1 -> lpos <- mid-1
| 1 -> fpos <- mid+1
| _ -> cont <- false
not cont
But I think that the recursive version is preferable: more idiomatic, as efficient as the iterative one because it uses tail calls.
To begin with, your algo would not terminate for value greater, than the rightmost words element (easy test case is find [|"a";"b";"c";"d"|] "e").
This matter being corrected and throwing in few minor optimizations, the final interactive implementation is not likely can be shorter, than below
let find (words: string[]) (value:string) =
let mutable lpos = words.Length - 1
if value.CompareTo(words.[lpos]) > 0 then
false
else
let mutable mid = 0
let mutable fpos = 0
let mutable cont = true
while fpos < lpos && cont do
mid <- (fpos + lpos) / 2
match sign(value.CompareTo(words.[mid])) with
| -1 -> lpos <- mid
| 1 -> fpos <- mid
| _ -> cont <- false
not cont
UPDATE: That's what happens when putting answer in a rush and without a computer around :(. The content striked-through above is not something to be proud of. As MiMo has already took care of all problems in the snippet above I'll try something different to vindicate myself, namely, try demonstrating how MiMo's recursive implementation after tail-call recursion elimination turns almost literally into his non-recursive one.
We'll do this in two steps: first use a pseudo-code with labels and gotos to illustrate what compiler does for eliminating this form of tail recursion, and then convert pseudo-code back into F# for getting an imperative version.
// Step 1 - pseudo-code with tail recursion substituted by goto
let find(words:string[]) (value:string) =
let mutable fpos = 0
let mutable lpos = words.Length - 1
findRec:
match fpos - lpos > 0 with
| true -> return false
| _ -> let mid = (fpos + lpos) / 2
match sign(value.CompareTo(words.[mid])) with
| -1 -> lpos <- mid - 1
goto findRec
| 1 -> fpos <- mid + 1
goto findRec
| _ -> return true
Now, in absence of goto we should come up with an equivalent construction while staying within legit set of F# constructions. The easiest approach would be using while...do construction in concert with a mutable state variable capable simultaneously of signaling while when to stop and carrying return value. A tuple of two Booleans would be sufficient for this purpose:
// Step 2 - conversion of pseudo-code back to F#
let find(words:string[]) (value:string) =
let mutable fpos = 0
let mutable lpos = words.Length - 1
let mutable state = (true,false)
while (fst state) do
match fpos - lpos > 0 with
| true -> state <- (false,false)
| _ -> let mid = (fpos + lpos) / 2
match sign(value.CompareTo(words.[mid])) with
| -1 -> lpos <- mid - 1
| 1 -> fpos <- mid + 1
| _ -> state <- (false,true)
snd state
Summing up, the difference between "a-la compiler optimized" recursive version and hand-picked imperative one is insignificant, indeed, which should, in my opinion, make evident that correctly arranged recursive version performance-wise is equivalent to imperative version, but, given conversion performed by compiler, leaves no space for blunders of stateful coding.
I would suggest a recursive solution like this:
let find (xs: _ []) x =
let rec loop i0 i2 =
match i2-i0 with
| 0 -> false
| 1 -> xs.[i0]=x
| di ->
let i1 = i0 + di/2
let c = compare x xs.[i1]
if c<0 then loop i0 i1
else c=0 || loop i1 i2
loop 0 xs.Length
F# converts the tail calls into gotos, of course:
internal static bool loop#4<a>(a[] xs, a x, int i0, int i2)
{
a a;
while (true)
{
int num = i2 - i0;
switch (num)
{
case 0:
return false;
case 1:
goto IL_50;
default:
{
int i3 = i0 + num / 2;
a = xs[i3];
int c = LanguagePrimitives.HashCompare.GenericComparisonIntrinsic<a>(x, a);
if (c < 0)
{
a[] arg_37_0 = xs;
a arg_35_0 = x;
int arg_33_0 = i0;
i2 = i3;
i0 = arg_33_0;
x = arg_35_0;
xs = arg_37_0;
}
else
{
if (c == 0)
{
return true;
}
a[] arg_4A_0 = xs;
a arg_48_0 = x;
int arg_46_0 = i3;
i2 = i2;
i0 = arg_46_0;
x = arg_48_0;
xs = arg_4A_0;
}
break;
}
}
}
return true;
IL_50:
a = xs[i0];
return LanguagePrimitives.HashCompare.GenericEqualityIntrinsic<a>(a, x);
}
public static bool find<a>(a[] xs, a x)
{
return File1.loop#4<a>(xs, x, 0, xs.Length);
}
Related
I'm having an issue with this implementation. It's giving me an error that "this expression to have type bool but here has unit" on the entire block starting at the first for loop and ending with the pown expression.
I'm not entirely sure what this means.
let rec detMat (m : int[,] ) : int =
let mutable det = 0
let mutable n = m.Length
let mutable i = 0
let mutable j = 0
let mutable j = 0
let mutable j1 = 0
let mutable j2 = 0
let mTmp = Array2D.create 0
if n = 1 then
det = m.[0, 0]
elif n = 2 then
det = m.[0, 0] * m.[1, 1] - m.[1, 0] * m.[0, 1]
else
det = 0
for j1 = 0 to n do
for i = 1 to n do
j2 = 0
for j = 0 to n do
if j <> j1 then
mTmp.[i-1, j2] <- m.[i, j]
j2 = j2 + 1
pown -1 (1 + j1 + 1) * m.[0, j1] * detMat(mTmp, n-1)
det
<- is the assignment operator for mutable variables.
Your code should be
det <- m.[0, 0]
det <- m.[0, 0] * m.[1, 1] - m.[1, 0] * m.[0, 1]
j2 <- j2 + 1
= is for equality, that's why you are getting the "this expression to have type bool" error. The second part, "but here has unit", means the compiler is expecting an arm of if to return a unit in the last expression. Carefully read this page to understand why the error message is so confusing: https://msdn.microsoft.com/en-us/library/dd233231.aspx
I'm working on a program that iterates over an input file, with a variable number of 'programs', and ending in '0'. My function run works fine if I start it from the top of the file, but for some reason a line is consumed by peeking to see if the next char is '0' (indicating the end of the file).
Here's my code:
let line_stream_of_channel channel =
Stream.from
(fun _ ->
try Some (input_line channel) with End_of_file -> None);;
let in_channel = open_in "dull.in" in
let line_stream = line_stream_of_channel in_channel in
while Stream.peek line_stream != Some "0" do
run in_channel;
print_string "...\n";
done;;
From what I've read, Stream.peek shouldn't consume a line, so maybe the problem doesn't come from that, but if not, I can't figure out what's doing it. Any ideas?
Edit Here's the entirety of my program:
let hello c =
print_char c;;
let hello_int c =
print_int c;
print_char '\n';;
let ios = int_of_string;;
let rec print_string_list = function
[] -> print_string "\n"
| h::t -> print_string h ; print_string " " ; print_string_list t;;
let rec print_int_list = function
[] -> print_string "\n"
| h::t -> print_int h ; print_string " " ; print_int_list t;;
let rec append l i =
match l with
[] -> [i]
| h :: t -> h :: (append t i);;
let line_stream_of_channel channel =
Stream.from
(fun _ ->
try Some (input_line channel) with End_of_file -> None);;
let string_to_int_list str_list int_list=
let len = List.length str_list in
for i = 0 to len - 1 do
int_list := append !int_list (ios (List.nth str_list i));
done;;
let get_option = function
| Some x -> x
| None -> raise (Invalid_argument "Option.get");;
let chomp_line ns in_channel =
let s = input_line in_channel in
let len = String.length s in
let start_pos = ref 0 in
for i = 0 to len do
if i == len then
let word = String.sub s !start_pos (i - !start_pos) in
ns := append !ns word;
else if s.[i] == ' ' then
let word = String.sub s !start_pos (i - !start_pos) in
ns := append !ns word;
start_pos := i + 1;
done;;
let run in_channel =
let ns = ref [] in
chomp_line ns in_channel;
let n = ios (List.nth !ns 0) in
let p = ios (List.nth !ns 1) in
let s = ios (List.nth !ns 2) in
print_string "num dulls: "; hello_int n;
print_string "num programs: "; hello_int p;
print_string "num state transitions: "; hello_int s;
let dull_sizes = ref [] in
chomp_line dull_sizes in_channel;
let int_dull_sizes = ref [] in
string_to_int_list !dull_sizes int_dull_sizes;
print_string "size of dulls: "; print_int_list !int_dull_sizes;
let program_sizes = ref [] in
let program_dulls = ref [] in
for i = 0 to p - 1 do
let program = ref [] in
chomp_line program in_channel;
program_sizes := append !program_sizes (List.nth !program 0);
program_dulls := append !program_dulls (List.nth !program 1);
done;
let int_program_sizes = ref [] in
string_to_int_list !program_sizes int_program_sizes;
print_string "program sizes: "; print_int_list !int_program_sizes;
print_string "program dulls: "; print_string_list !program_dulls;
let transitions = ref [] in
chomp_line transitions in_channel;
let int_transitions = ref [] in
string_to_int_list !transitions int_transitions;
for i = 0 to s - 1 do
hello_int (List.nth !int_transitions i)
done
;;
let in_channel = open_in "dull.in" in
let line_stream = line_stream_of_channel in_channel in
while Stream.peek line_stream <> Some "0" do
run in_channel;
done;;
And here's a sample input:
2 2 3
500 600
100 A
200 B
2 1 2
5 4 8
100 400 200 500 300
250 AC
360 ACE
120 AB
40 DE
2 3 4 -3 1 2 -2 1
0
(!=) is physical (pointer) inequality, and the test fails to detect your end mark 0. When 0 is peeked, Stream.peek returns Some 0, but it is a different entity from Some 0 of the right hand of the inequality check, and therefore the loop never terminates until it crashes at EOF.
The following demonstrates what is happening:
# Some 0 != Some 0;;
- : bool = true
# let x = Some 0 in x != x;;
- : bool = false
Use (<>), structural inequality here. Except it and the omitted run_in_channel part, the code works fine for me.
A golden rule: do not use physical equality (==) and (!=) unless you really need them. Normally, stick to structural equalities (=) and (<>).
-- edit --
There was another issue in the code which was not originally revealed.
Once you create a stream from an in_channel. Do not touch it by yourself, until you want to close it by close_in! Let the stream the only reader of it.
The benefit of the stream is that once created, you are freed from taking care of when the actual readings happen. You could still access the channel directly, but it just ruins the benefit completely. Just do not do it. Use Stream.next or Stream.peek instead of input_line in your run.
let compareDiagonal p x y =
System.Math.Abs((int)(x - (fst p))) <> System.Math.Abs((int)(y - (snd p)));;
let isAllowed p = function
| [] -> true
| list -> List.forall (fun (x, y) -> fst p <> x && snd p <> y && (compareDiagonal p x y)) list;;
let rec solve col list =
let solCount : int = 0
match col with
| col when col < 8 ->
for row in [0 .. 7] do
solCount = solCount + if isAllowed (row, col) list then solve (col + 1) ((row, col) :: list) else 0
solCount
| _ -> 1;;
let solCount = solve 0 [];;
solCount;;
I am getting the error
solCount = solCount + if isAllowed (row, col) list then (solve (col + 1) ((row, col) :: list)) else 0
------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
stdin(335,13): warning FS0020: This expression should have type 'unit', but has type 'bool'. If assigning to a property use the syntax 'obj.Prop <- expr'.
Why am I not able to return the number?
There are two related problems.
By default in F# variable are immutable. If you want a mutable variable, you have to declare it, like this:
let mutable solCount : int = 0
And then when you assign values to it instead of using = you have to use <- like this:
solCount <- solCount + if isAllowed (row, col) list then solve (col + 1) ((row, col) :: list) else 0
A complete example followed.
HOWEVER, this is not the correct functional way to do something like this. Instead of using a loop to add up values, use a recursive function to return the cumulative value as you go. Using F# the way functional programs are designed to be used will almost always yield better results, although it takes some getting used to.
Your original example with mutable, not the "functional way":
let compareDiagonal p x y =
System.Math.Abs((int)(x - (fst p))) <> System.Math.Abs((int)(y - (snd p)));;
let isAllowed p = function
| [] -> true
| list -> List.forall (fun (x, y) -> fst p <> x && snd p <> y && (compareDiagonal p x y)) list;;
let rec solve col list =
let mutable solCount : int = 0
match col with
| col when col < 8 ->
for row in [0 .. 7] do
solCount <- solCount + if isAllowed (row, col) list then solve (col + 1) ((row, col) :: list) else 0
solCount
| _ -> 1;;
let solCount = solve 0 [];;
solCount;;
First shot at Euler #3 in F#, and I would like to return a boolean more elegantly than this mutable value.
// A number is prime if can only divide by itself and 1. Can only be odd.
let isPrime x =
if (x%2L = 0L) then
false
else
let mutable result = true
for i in 3L..x/2L do
if (x%i = 0L) then
result <- false
result
let a = isPrime(17L)
// True
printfn "%b" a
The L's are as I'm forcing the function to return bigints (there has to be a better way too, but 1 step at a time)....
Edit
Gradbot's solution
let isPrime x =
// A prime number can't be even
if (x%2L = 0L) then
false
else
// Check for divisors (other than 1 and itself) up to half the value of the number eg for 15 will check up to 7
let maxI = x / 2L
let rec notDivisible i =
// If we're reached more than the value to check then we are prime
if i > maxI then
true
// Found a divisor so false
elif x % i = 0L then
false
// Add 2 to the 'loop' and call again
else
notDivisible (i + 2L)
// Start at 3
notDivisible 3L
you can replace the else clause with a forall:
Seq.forall (fun i -> x % i <> 0L) { 3L .. x/2L }
and then further reduce it to a single expression:
x % 2L <> 0L && Seq.forall (fun i -> x % i <> 0L) { 3L .. x/2L }
although I see no reason for treating 2 differently, you can simply do:
let isPrime x =
{ 2L .. x/2L } |> Seq.forall (fun i -> x % i <> 0L)
The following F# code gives the correct answer to Project Euler problem #7:
let isPrime num =
let upperDivisor = int32(sqrt(float num)) // Is there a better way?
let rec evaluateModulo a =
if a = 1 then
true
else
match num % a with
| 0 -> false
| _ -> evaluateModulo (a - 1)
evaluateModulo upperDivisor
let mutable accumulator = 1 // Would like to avoid mutable values.
let mutable number = 2 // ""
while (accumulator <= 10001) do
if (isPrime number) then
accumulator <- accumulator + 1
number <- number + 1
printfn "The 10001st prime number is %i." (number - 1) // Feels kludgy.
printfn ""
printfn "Hit any key to continue."
System.Console.ReadKey() |> ignore
I'd like to avoid the mutable values accumulator and number. I'd also like to refactor the while loop into a tail recursive function. Any tips?
Any ideas on how to remove the (number - 1) kludge which displays the result?
Any general comments about this code or suggestions on how to improve it?
Loops are nice, but its more idiomatic to abstract away loops as much as possible.
let isPrime num =
let upperDivisor = int32(sqrt(float num))
match num with
| 0 | 1 -> false
| 2 -> true
| n -> seq { 2 .. upperDivisor } |> Seq.forall (fun x -> num % x <> 0)
let primes = Seq.initInfinite id |> Seq.filter isPrime
let nthPrime n = Seq.nth n primes
printfn "The 10001st prime number is %i." (nthPrime 10001)
printfn ""
printfn "Hit any key to continue."
System.Console.ReadKey() |> ignore
Sequences are your friend :)
You can refer my F# for Project Euler Wiki:
I got this first version:
let isPrime n =
if n=1 then false
else
let m = int(sqrt (float(n)))
let mutable p = true
for i in 2..m do
if n%i =0 then p <- false
// ~~ I want to break here!
p
let rec nextPrime n =
if isPrime n then n
else nextPrime (n+1)
let problem7 =
let mutable result = nextPrime 2
for i in 2..10001 do
result <- nextPrime (result+1)
result
In this version, although looks nicer, but I still does not early break the loop when the number is not a prime. In Seq module, exist and forall methods support early stop:
let isPrime n =
if n<=1 then false
else
let m = int(sqrt (float(n)))
{2..m} |> Seq.exists (fun i->n%i=0) |> not
// or equivalently :
// {2..m} |> Seq.forall (fun i->n%i<>0)
Notice in this version of isPrime, the function is finally mathematically correct by checking numbers below 2.
Or you can use a tail recursive function to do the while loop:
let isPrime n =
let m = int(sqrt (float(n)))
let rec loop i =
if i>m then true
else
if n%i = 0 then false
else loop (i+1)
loop 2
A more functional version of problem7 is to use Seq.unfold to generate an infinite prime sequence and take nth element of this sequence:
let problem7b =
let primes =
2 |> Seq.unfold (fun p ->
let next = nextPrime (p+1) in
Some( p, next ) )
Seq.nth 10000 primes
Here's my solution, which uses a tail-recursive loop pattern which always allows you to avoid mutables and gain break functionality: http://projecteulerfun.blogspot.com/2010/05/problem-7-what-is-10001st-prime-number.html
let problem7a =
let isPrime n =
let nsqrt = n |> float |> sqrt |> int
let rec isPrime i =
if i > nsqrt then true //break
elif n % i = 0 then false //break
//loop while neither of the above two conditions are true
//pass your state (i+1) to the next call
else isPrime (i+1)
isPrime 2
let nthPrime n =
let rec nthPrime i p count =
if count = n then p //break
//loop while above condition not met
//pass new values in for p and count, emulating state
elif i |> isPrime then nthPrime (i+2) i (count+1)
else nthPrime (i+2) p count
nthPrime 1 1 0
nthPrime 10001
Now, to specifically address some of the questions you had in your solution.
The above nthPrime function allows you to find primes at an arbitrary position, this is how it would look adapted to your approach of finding specifically the 1001 prime, and using your variable names (the solution is tail-recursive and doesn't use mutables):
let prime1001 =
let rec nthPrime i number accumulator =
if accumulator = 1001 then number
//i is prime, so number becomes i in our next call and accumulator is incremented
elif i |> isPrime then prime1001 (i+2) i (accumulator+1)
//i is not prime, so number and accumulator do not change, just advance i to the next odd
else prime1001 (i+2) number accumulator
prime1001 1 1 0
Yes, there is a better way to do square roots: write your own generic square root implementation (reference this and this post for G implementation):
///Finds the square root (integral or floating point) of n
///Does not work with BigRational
let inline sqrt_of (g:G<'a>) n =
if g.zero = n then g.zero
else
let mutable s:'a = (n / g.two) + g.one
let mutable t:'a = (s + (n / s)) / g.two
while t < s do
s <- t
let step1:'a = n/s
let step2:'a = s + step1
t <- step2 / g.two
s
let inline sqrtG n = sqrt_of (G_of n) n
let sqrtn = sqrt_of gn //this has suffix "n" because sqrt is not strictly integral type
let sqrtL = sqrt_of gL
let sqrtI = sqrt_of gI
let sqrtF = sqrt_of gF
let sqrtM = sqrt_of gM