This expression has type int but is here used with type unit - syntax

I'm trying to get the exact equivalent (not functional) of this vb.net code in F#:
Function FastPow(ByVal num As Double, ByVal exp As Integer) As Double
Dim res As Double = 1
If exp < 1 Then
If exp = 0 Then Return res
exp = -exp
num = 1 / num
End If
Do While exp > 1
If exp Mod 2 = 1 Then
res = res * num
num = num * num
exp = exp >> 1
Loop
Return res * num
End Function
I wrote this:
let FastPow num exp =
let mutable ex = exp
let mutable res = 1
let mutable n = num
if ex < 1 then
if ex = 0 then res
ex <- -ex
n <- 1 / n
while ex > 1 do
if (ex % 2 = 1) then
res <- res * n
n <- n * n
exp >>> 1
res * n
but in the line "if ex = 0 then res" at res I got an error:
"This expression has type int but is here used with type unit".
I cannot understand why it gives me that error.
Edit: i actually got a warning as well:
"This expression should have type 'unit', but has type 'int'."
at "if (ex % 2 = 1) then"

In F#, a function's return value is the last expression evaluated in the function. So, lets focus on the following:
if ex < 1 then
if ex = 0 then res (* <--- this is not an early return *)
ex <- -ex (* <--- F# evaluates this code after the *)
n <- 1 / n (* if statement *)
Additionally, if statements have return values, which also happens to be the last value executed in the if statement. If an if statement isn't the return value of a function, it should have the return type unit. Notice that variable assignment has a return type of unit.
We need to rewrite your code to accomodate your early return, so we can do this:
let FastPow2 num exp =
if exp = 0 then 1
else
let mutable ex = exp
let mutable res = 1
let mutable n = num
if ex < 1 then
ex <- -ex
n <- 1 / n
while ex > 1 do
if (ex % 2 = 1) then (* still have a bug here *)
res <- res * n
n <- n * n
exp >>> 1 (* <--- this is not a variable assignment *)
res * n
We still have a bug, although I think F# is reporting the error in the wrong place. The expression exp >>> 1 returns an int, it does not assign any variables, so its not equivalent to your original C# code. I think you meant to use the ex variable instead. We can fix your code as follows:
let FastPow2 num exp =
if exp = 0 then 1
else
let mutable ex = exp
let mutable res = 1
let mutable n = num
if ex < 1 then
ex <- -ex
n <- 1 / n
while ex > 1 do
if (ex % 2 = 1) then
res <- res * n
n <- n * n
ex <- ex >>> 1
res * n
Now your function is fixed, but its really really ugly. Lets convert it to more idiomatic F#. You can replace the if statement with pattern matching, and replace the while loop with recursion:
let FastPow2 num exp =
match exp with
| 0 -> 1
| _ ->
let rec loop ex res n =
if ex > 1 then
let newRes = if ex % 2 = 1 then res * n else res
loop (ex >>> 1) newRes (n * n)
else res * n
let ex, n = if exp < 1 then (-exp, 1 / num) else (exp, num)
loop ex 1 n
Much better! Theres still some more room to beautify this function, but you get the idea :)

The problem is for an if statment to resolve to a value rather than unit, you need both the "then" part and the "else" part, both of which resolve to the same type.
For example:
let a = if true then 1;;
Will generate the same error - expression has type int but used with type unit.
However:
let a = if true then 1 else 0;;
Will evaluate to int without an error.

This is about as close as you can get, as others have already said you can't jump out of the middle of a functional and there's one place were you don't update a variable (at the bottom of the while).
let FastPow num exp =
let mutable exp = exp
let mutable res = 1
let mutable n = num
match exp with
| O -> n <- num
| _ when exp < 1 ->
exp <- -exp
n <- 1 / n
| _ ->
while exp > 1 do
if (exp % 2 = 1) then
res <- res * n
n <- n * n
exp <- exp >>> 1
res * n
I could be more beautiful if it was written more functionally.

It means that after then there should be some expression, but you have integer value. You cannot jump out from the middle of the function.
Edit
"If" didn't work because of
ex >>> 1
should be
ex <- ex >>> 1
Here's code that works:
let FastPow num exp =
let calcExp num exp =
let mutable res = 1.0
let mutable n = num
let mutable ex = exp
while ex > 1 do
if ((ex % 2) = 1) then
res <- res * n
n <- n * n
ex <- ex >>> 1
res * n
match exp with
| ex when ex = 0 -> 1.0
| ex when ex < 0 -> calcExp (1.0/num) -exp
| _ -> calcExp num exp
I just take out calculation as separate function, and at the end there is checking for arguments

Thanks for the answers. This is the current non-functional version.
let FastPow num exp =
let mutable ex = exp
let mutable res = 1.0
let mutable n = num
if ex = 0 then 1.0
else
if ex < 1 then
ex <- -ex
n <- 1.0 / n
while ex > 1 do
if (ex % 2 = 1) then res <- res * n
n <- n * n
ex <- ex >>> 1
res * n
Now that I have a working version I will try to make it more functional but that's outside the scope of this question.
EDIT: I got better results that I expected so I will post the recursive version optimized for speed (slightly faster than the iterative version and about 10% faster than the C# iterative version (!!!) in my computer):
let rec loop res num exp =
if exp = 0 then res
elif (exp % 2) = 1 then loop (res * num) (num * num) (exp / 2)
else loop res (num * num) (exp / 2)
let FP num exp =
let n = if exp < 0 then 1.0 / num else num
loop 1.0 n (Math.Abs(exp))

Related

How to display only the program output in utop on the VS Code terminal and not all the instructions one after the other

(*redefining the power function for integers*)
let rec ( ** ) v n = if n = 0 then 1 else v * (( ** ) v (n-1));;
let rec sommation n =
if n = 0 then 0 else -1**(n/3) * n**(2+ (-1)**n) + sommation (n-1);;
print_int (sommation 7);;
When I run the above program in VS Code by selecting all lines of code then press Ctrl+Enter, this is what displays in the terminal:
└──────────────────────────────────────────────────────────────┘
Type #utop_help for help about using utop.
─( 17:07:51 )─< command 0 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─utop # (*redefining the power function for integers*)
let rec ( ** ) v n = if n = 0 then 1 else v * (( ** ) v (n-1));;
val ( ** ) : int -> int -> int = <fun>
─( 17:07:51 )─< command 1 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─utop #
let rec sommation n =
if n = 0 then 0 else -1**(n/3) * n**(2+ (-1)**n) + sommation (n-1);;
val sommation : int -> int = <fun>
─( 17:07:54 )─< command 2 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─utop #
print_int (sommation 7);;
160- : unit = ()
─( 17:07:54 )─< command 3 >───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────{ counter: 0 }─
As you can see, it displays the lines of my program one after the other, which makes it take a long time to display the output which is 160
How can I fix this problem?
Once you start writing large programs rather than testing short snippets in the toplevel, it probably makes sense to save them as a file, and execute that file. If you go beyond one file, you should probably investigate using Dune to manage the build process.
Consider your example. Rather than a bunch of expressions separated by ;; tokens, let's put that into a file test.ml.
(*redefining the power function for integers*)
let rec ( ** ) v n =
if n = 0 then 1
else v * (( ** ) v (n-1))
let rec sommation n =
if n = 0 then 0
else -1**(n/3) * n**(2+ (-1)**n) + sommation (n-1)
let () =
print_int (sommation 7)
In a program, your last expression would not be valid. At the top level of a program, we cannot have bare expressions, so we bind it to ().
Now you can execute this as ocaml test.ml in your shell or compile it with ocamlc or ocamlopt.

F#. Terminated due to timeout when solving Project Euler #3 problem

I told about that problem: https://www.hackerrank.com/contests/projecteuler/challenges/euler003
I am trying to solve this problem as follows:
open System
let isPrime n =
match n with
| _ when n > 3L && (n % 2L = 0L || n % 3L = 0L) -> false
| _ ->
let maxDiv = int64(System.Math.Sqrt(float n)) + 1L
let rec f d i =
if d > maxDiv then
true
else
if n % d = 0L then
false
else
f (d + i) (6L - i)
f 5L 2L
let primeFactors n =
let rec getFactor num proposed acc =
match proposed with
| _ when proposed = num -> proposed::acc
| _ when num % proposed = 0L -> getFactor (num / proposed) proposed (proposed::acc)
| _ when isPrime num -> num::acc
| _ -> getFactor num (proposed + 1L) acc
getFactor n 2L []
let pe3() =
for i = 1 to Console.ReadLine() |> int do
let num = Console.ReadLine() |> int64
let start = DateTime.Now
primeFactors num
|> List.max
|> printfn "%i"
let elapsed = DateTime.Now - start
printfn "elapsed: %A" elapsed
pe3()
There are results of my testing:
Input: 10 Output: 5 Elapsed time: 00:00:00.0562321
Input: 123456789 Output: 3803 Elapsed time: 00:00:00.0979232
Input: 12345678999 Output: 1371742111 Elapsed time: 00:00:00.0520280
Input: 987654321852 Output: 680202701 Elapsed time: 00:00:00.0564059
Input: 13652478965478 Output: 2275413160913 Elapsed time:
00:00:00.0593369
Input: 99999999999999 Output: 909091 Elapsed time: 00:00:00.1260673
But I anyway get Terminated due to timeout in Test Case 5. What can I do?
There is a solution:
open System
let primeFactors n =
let rec getFactor num proposed acc =
match proposed with
| _ when proposed*proposed > num -> num::acc
| _ when num % proposed = 0L -> getFactor (num / proposed) proposed (proposed::acc)
| _ -> getFactor num (proposed + 1L) acc
getFactor n 2L []
let pe3() =
for i = 1 to Console.ReadLine() |> int do
printfn "%i" (primeFactors (Console.ReadLine() |> int64)).Head
pe3()
Thanks Will Ness and rici.
There is no need to write super sophisticated code for this challenge. A simple algorithm to enumerate a number's prime factors will do the trick. My code creates a seq of the prime factors, then finds the maximum, and prints it. The rest of the code shows a nice functional way of handling processing of lines read from standard input.
module Auxiliaries =
let isNull (x : 'a when 'a : not struct) =
match box x with
| null -> true
| _ -> false
let refAsOption x =
if isNull x then None else Some x
let readLinesFromTextReader r =
let tryRdLn (r : System.IO.TextReader) =
try refAsOption (r.ReadLine ()) with _ -> None
let gen r =
tryRdLn r |> Option.map (fun s -> (s, r))
Seq.unfold gen r
module Contest =
let factors num =
let next n =
if n = 2L then 3L
elif n % 6L = 1L then n + 4L
else n + 2L
let rec loop nn ct lf =
seq {
if ct * ct > nn then
if nn > lf then yield nn
elif nn % ct = 0L then
yield ct
yield! loop (nn / ct) ct ct
else
yield! loop nn (next ct) lf
}
loop num 2L 0L
let euler003 n = factors n |> Seq.max
let () =
Auxiliaries.readLinesFromTextReader stdin
|> Seq.skip 1
|> Seq.map (int64 >> euler003)
|> Seq.iter stdout.WriteLine

Something wrong with my PollardP1_rho code but I don't know how to fix it

I tried to use MillerRabin + PollardP1_rho method to factorize an integer into primes in Python3 for reducing time complexity as much as I could.But it failed some tests,I knew where the problem was.But I am a tyro in algorithm, I didn't know how to fix it.So I will put all relative codes here.
import random
def gcd(a, b):
"""
a, b: integers
returns: a positive integer, the greatest common divisor of a & b.
"""
if a == 0:
return b
if a < 0:
return gcd(-a, b)
while b > 0:
c = a % b
a, b = b, c
return a
def mod_mul(a, b, n):
# Calculate a * b % n iterately.
result = 0
while b > 0:
if (b & 1) > 0:
result = (result + a) % n
a = (a + a) % n
b = (b >> 1)
return result
def mod_exp(a, b, n):
# Calculate (a ** b) % n iterately.
result = 1
while b > 0:
if (b & 1) > 0:
result = mod_mul(result, a, n)
a = mod_mul(a, a, n)
b = (b >> 1)
return result
def MillerRabinPrimeCheck(n):
if n in {2, 3, 5, 7, 11}:
return True
elif (n == 1 or n % 2 == 0 or n % 3 == 0 or n % 5 == 0 or n % 7 == 0 or n % 11 == 0):
return False
k = 0
u = n - 1
while not (u & 1) > 0:
k += 1
u = (u >> 1)
random.seed(0)
s = 5 #If the result isn't right, then add the var s.
for i in range(s):
x = random.randint(2, n - 1)
if x % n == 0:
continue
x = mod_exp(x, u, n)
pre = x
for j in range(k):
x = mod_mul(x, x, n)
if (x == 1 and pre != 1 and pre != n - 1):
return False
pre = x
if x != 1:
return False
return True
def PollardP1_rho(n, c):
'''
Consider c as a constant integer.
'''
i = 1
k = 2
x = random.randrange(1, n - 1) + 1
y = x
while 1:
i += 1
x = (mod_mul(x, x, n) + c) % n
d = gcd(y - x, n)
if 1 < d < n:
return d
elif x == y:
return n
elif i == k:
y = x
k = (k << 1)
result = []
def PrimeFactorsListGenerator(n):
if n <= 1:
pass
elif MillerRabinPrimeCheck(n) == True:
result.append(n)
else:
a = n
while a == n:
a = PollardP1_rho(n, random.randrange(1,n - 1) + 1)
PrimeFactorsListGenerator(a)
PrimeFactorsListGenerator(n // a)
When I tried to test this:
PrimeFactorsListGenerator(4)
It didn't stop and looped this:
PollardP1_rho(4, random.randrange(1,4 - 1) + 1)
I have already tested the functions before PollardP1_rho and they work normally,so I know the function PollardP1_rho cannot deal the number 4 correctly,also the number 5.How can I fix that?
I have solved it myself.
There is 1 mistake in the code.
I should not use a var 'result' outside of the function as a global var,I should define in the function and use result.extend() to ensure the availability of the whole recursive process.So I rewrote PollardP1_rho(n, c) and PrimeFactorsListGenerator(n):
def Pollard_rho(x, c):
'''
Consider c as a constant integer.
'''
i, k = 1, 2
x0 = random.randint(0, x)
y = x0
while 1:
i += 1
x0 = (mod_mul(x0, x0, x) + c) % x
d = gcd(y - x0, x)
if d != 1 and d != x:
return d
if y == x0:
return x
if i == k:
y = x0
k += k
def PrimeFactorsListGenerator(n):
result = []
if n <= 1:
return None
if MillerRabinPrimeCheck(n):
return [n]
p = n
while p >= n:
p = Pollard_rho(p, random.randint(1, n - 1))
result.extend(PrimeFactorsListGenerator(p))
result.extend(PrimeFactorsListGenerator(n // p))
return result
#PrimeFactorsListGenerator(400)
#PrimeFactorsListGenerator(40000)
There is an additional tip: You don't need to write a function mod_mul(a, b, n) at all, using Python built-in pow(a, b, n) will do the trick and it is fully optimized.

SML finding a sum of squares/halves using other functions

So I want to find the sum of applying function f to the first n integers, when the sum of applying f to the first n integers is f applied to n plus the sum of applying f to the first n-1 integers, as in:
- fun inc x = x+1;
> val inc = fn : inet -> int
- sumF inc 3;
> 9 : int i.e. inc 3+inc 2+ inc 1+ 0
and my sumF looks like this now:
- fun sumF 0 = 0 | sumF n = sumF(n) + sumF(n-1);
val sumF = fn : int -> int
- sumF inc 3;
stdIn:15.1-15.11 Error: operator and operand don't agree [tycon mismatch]
operator domain: int
operand: int -> int
in expression:
sumF inc
As you can see I get an error, so maybe anyone knows how to fix it? Because later on, I want to write sumSq (sumSq n = (nn) + sumSq(n-1)) and sumHalf (sumSq n = (nn) + sumSq(n-1)), using sumF.
Thanks!
Here is a possible solution:
fun sumF f 0 = 0
| sumF f n = f n + sumF f (n - 1)
Your problem is, that you don't actually use the inc function in the definition of sumF function. You define the sumF function with only one argument of type int, but then you call this function with "two arguments". Your function call sumF inc 3 is interpreted as ((sumF inc) 3), and since the type of inc is int -> int, but the function expects the argument of type int, you get the error. And, besides this, your function has an additional problem - it creates infinite loop, since you call sumF n in the definition of sumF n.
You can call the function above as
- fun inc x = x + 1;
val inc = fn : int -> int
- sumF inc 3;
val it = 9 : int
or a bit shorter with anonymous function:
- sumF (fn x => x + 1) 3;
val it = 9 : int
Regards, Špela

algorithm to simulate multiplication by addition

How to design an algorithm to simulate multiplication by addition. input two integers. they may be zero, positive or negative..
def multiply(a, b):
if (a == 1):
return b
elif (a == 0):
return 0
elif (a < 0):
return -multiply(-a, b)
else:
return b + multiply(a - 1, b)
some pseudocode:
function multiply(x, y)
if abs(x) = x and abs(y) = y or abs(x) <> x and abs(y) <> y then sign = 'plus'
if abs(x) = x and abs(y) <> y or abs(x) <> x and abs(y) = y then sign = 'minus'
res = 0
for i = 0 to abs(y)
res = res + abs(x)
end
if sign = 'plus' return res
else return -1 * res
end function
val:= 0
bothNegative:=false
if(input1 < 0) && if(input2 < 0)
bothNegative=true
if(bothNegative)
smaller_number:=absolute_value_of(smaller_number)
for [i:=absolute_value_of(bigger_number);i!=0;i--]
do val+=smaller_number
return val;
mul(a,b)
{
sign1=sign2=1;
if(a==0 || b==0)
return 0;
if(a<0){
sign1=-1;
a=-a;
}
if(b<0){
sign2=-1;
b=-b;
}
s=a;
for(i=1;i<b;i++)
s+=a;
if(sign1==sign2)
return s;
else
return -s;
}
How about this for integers:
int multiply(int a, int b)
{
int product = 0;
int i;
if ( b > 0 )
{
for(i = 0; i < b ; i++)
{
product += a;
}
}
else
{
for(i = 0; i > b ; i--)
{
product -= a;
}
}
return product;
}
I got here because I was looking for multiplication algorithm without using * operation. All I see here is just adding or subtracting number n-times. It's O(n) and it's ok, but...
If you have bitwise shift operations you can get O(log n) algorithm for multiplication.
Here is my pseudocode:
function mul(n, x)
if n < 0 then # 'n' cannot be negative
n := -n
x := -x
endif
y := 0
while n != 0 do
if n % 2 == 0 then
x := x << 1 # x := x + x
n := n >> 1 # n := n / 2
else
y := y + x
x := x << 1 # x := x + x
n := n - 1 # n := (n-1)/2
n := n >> 1
endif
endwhile
return y # y = n * x
end
Remember that function above for mul(1000000, 2) is O(log 1000000) and for mul(2, 1000000) is only O(log 2).
Of course, you will get the same results, but keep in mind that the order of the parameters in function call does matter.
Edit: sidenote for using n % 2
Implementation of n % 2 using bitwise shift
It's pretty straightforward. First divide n by 2, then multiply n by 2 and check if n has changed. Pseudocode:
function is_even(n)
n_original := n
n := n >> 1 # n := n / 2
n := n << 1 # n := n * 2
if n = n_original then
return true # n is even
else
return false # n is not even
endif
end
Implementation of n % 2 using bitwise and
function is_even(n)
if n and 1 = 0 then
return true
else
return false
endif
end

Resources