I'm writing a function in sml using emacs and when I try to compile this code
fun tryDivide small n =
if n = 1 then true
else if ((small mod n) = 0) then tryDivide small (n-1)
else false
fun lcmHelper small div =
if tryDivide (small div) = false then lcmHelper ((small+div) div)
else small
(*Start by calling this*)
fun lcm d =
val small = d
lcmHelper (small d)
It is supposed to find the lowest value that can be divided by d (fun lcm d)
I am pretty sure that the algorithm works, but there are syntax errors.
At the start of the "fun lcm d =" I get an error that says "Error Inserting EQUALOP"
Any ideas what might be causing this?
Thanks in advance!
fun lcm d =
let
val small = d
in
lcmHelper (small d)
end
Related
listX n = xs
if sum[x | x <- [2, 4..n-1], y <- [1..n-1], y `rem` x == 0] == y
then insert y xs
else return ()
Alright, first time trying to work with Haskell, and only having novice Java knowledge has led to some problems.
What I was trying to do, was to define the result of the function listX n as a list called xs.
My idea was that the program would grab every number of from 1 to n, and check if it was equal to the sum of its positive divisors.
Clearly, I have failed horribly and need help, pointers to concepts I haven't understood is extremely appreciated.
Your main problem seems to be that you still think imperative (with the insert) - also () is the value unit - you probably wanted to write [] (the empty list) instead - but still the xs here is totally undefined so you would have to fix this too (and I don't see how to be honest).
perfect numbers
I think I can see a basic idea in there, and I think the best way to fix this is to go full list-comprehension (as you seem to understand them quite well) - here is a version that should work:
listX n = [ x | x <- [1..n], sum [ y | y <- [1..x-1], x `mod` y == 0] == x]
As you can see I changed this a bit - first I check all x from 1 to n if they could be perfect - and I do this by checking by summing up all proper divisors and checking if the sum is equal to x (that's the job of the sum [...] == x part) - in case you don't know this works because you can add guards to list comprehensions (the sum [..] == x filters out all values of x where this is true).
a nicer version
to make this a bit more readable (and separate the concerns) I would suggest writing it that way:
properDivisors :: Integer -> [Integer]
properDivisors n = [ d | d <- [1..n-1], n `mod` d == 0]
isPerfect :: Integer -> Bool
isPerfect n = sum (properDivisors n) == n
perfectNumbers :: [Integer]
perfectNumbers = filter isPerfect [1..]
perfectNumbersUpTo :: Integer -> [Integer]
perfectNumbersUpTo n = takeWhile (<= n) perfectNumbers
I'm learning OCaml (so forgive my style) and am trying to write a function that generates a list of prime numbers up to some upper bound. I've managed to do this in several different ways, all of which work until you scale them to a relatively high upper bound.
How can I change these (any of them) so that the recursion doesn't fill up the stack? I thought my while loop version would achieve this, but apparently not!
Generator
let primes max =
let isPrime p x =
let hasDivisor a = (x mod a = 0) in
not (List.exists hasDivisor p) in
let rec generate p test =
if test < max then
let nextTest = test + 2 in
if isPrime p test then generate (test :: p) nextTest
else generate p nextTest
else p in
generate [5; 3; 2] 7;;
This has been my most successful solution insofar as it doesn't immediately overflow the stack when running primes 2000000;;. However it just sits there consuming CPU; I can only assume it will complete eventually! The following alternatives all have the stack overflow problem:
Recursive Sieve of Eratosthenes
let primes max =
let rec sieve found toTest =
let h = List.hd toTest
and t = List.tl toTest in
let newPrimes = h :: found
and doesntDivide x = (x mod h <> 0) in
let nonDivisors = List.filter doesntDivide t in
if nonDivisors = [] then newPrimes
else sieve newPrimes nonDivisors in
let rec range a b =
if a > b then []
else a :: range (a + 1) b in
let p = range 2 max in
sieve [] p;;
Recursive Sieve of Eratosthenes v2
let primes max =
let rec sieve toTest =
let h = List.hd toTest
and t = List.tl toTest in
let doesntDivide x = (x mod h <> 0) in
let nonDivisors = List.filter doesntDivide t in
if nonDivisors = [] then [h]
else (h :: sieve nonDivisors) in
let rec range a b =
if a > b then []
else a :: range (a + 1) b in
let p = range 2 max in
sieve p;;
While Loop Sieve of Eratosthenes
let primes max =
let rec range a b =
if a > b then []
else a :: range (a + 1) b in
let tail = ref (range 2 max)
and p = ref [] in
while !tail <> [] do
let h = List.hd !tail
and t = List.tl !tail in
let doesntDivide x = (x mod h <> 0) in
let newTail = ref (List.filter doesntDivide t) in
tail := !newTail;
p := h :: !p
done;
!p;;
The stack overflows occur because your range function is not tail recursive. One that works is, e.g.
let rec range store a b =
if a > b then store
else range (a :: store) (a + 1) b
in
let p = List.rev (range [] 2 max) in
With that definition, and a format line, gives
$ ocamlopt -o primes2 primes2.ml
$ ./primes2
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
...
Since you're learning, I'll give you some unsolicited style comments as well :)
Don't use hd and tl. Prefer pattern matching. Then the compiler can tell you the cases you missed. E.g.
let rec sieve found toTest =
let h = List.hd toTest
and t = List.tl toTest in
would be
let rec sieve found = function
| h :: t -> ...
| [] -> Error handling...
Don't use x = []. Use pattern patching.
match x with
| [] -> ...
| h::t -> ...
Use anonymous functions rather than short (i.e. <= 1 line) named single use functions:
let doesntDivide x = (x mod h <> 0) in
let nonDivisors = List.filter doesntDivide t in
let nonDivisors = List.filter (fun x -> (x mod h <> 0)) t in
Use imperative features sparingly.
Your algorithms that you claim are the Sieve of Eratosthenes actually are not; they use trial division instead of sieving, which is easy to spot by looking for a comparison of a remainder (the mod operator) to zero. Here's a simple implementation of the Sieve of Eratosthenes, in pseudocode instead of Ocaml because it's been a long time since I wrote Ocaml code:
function primes(n)
sieve := makeArray(2..n, True)
for p from 2 to n
if sieve[p]
output p
for i from p*p to n step p
sieve[i] := False
That can be optimized further, though for small limits like n = 2000000 there is little point in doing so; in any case, a sieve will be very much faster than the trial division that you are using. If you're interested in programming with prime numbers, I modestly recommend this essay at my blog.
This function takes two integers and returns the list of all integers in the range [a,b]
This is the solution that I wrote.
let rec range_rec l a b =
if (a=b) then l#[b]
else range_rec (l#[a], a+1, b);;
let range a b = range_rec [] a b;;
I'm hitting an error "Error: This expression has type int list * int * int but an expression was expected of type int". Can someone throw some light on why am I getting this error?
Thanks.
It should look like this:
let rec range_rec l a b =
if a = b then l # [b]
else range_rec (l # [a]) (a + 1) b;;
let range a b = range_rec [] a b;;
What I've done:
Changed loop to range_rec
Changed (l#[a], a+1, b) to (l # [a]) (a + 1) b. The first is a triplet and the second is 3 arguments to a curried function.
Notice that if (a = b) then can be written as if a = b then.
Last, the function can be made more efficient by using :: instead of # by looping "backwards". For example like gasche have shown.
The l # [elem] operation is terrible from a performance perspective : as a # b is linear in the length of a, adding an element to the end of list is linear in the length of the list, making your whole range_rec definition quadratic in |b-a|. The way to go is to change your code so that you can use the constant-time elem::l operation instead.
let rec range a b =
if a > b then []
else a :: range (a + 1) b
You may make additional optimizations such as making it tail-recursive, but at least the complexity of this solution is right.
To improve on the solution already suggested by gasche, this can be made tail-recursive.
let int_range a b =
let rec int_range_rec l a b =
if a > b then l
else int_range_rec (b :: l) a (b - 1)
in (int_range_rec [] a b);;
I'm writing a program in ocaml containing some loops "for", my problem is that for each of these cycles you receive this message: "warning 10 : this expression should have type unit. "
Example :
let f q p rho=
let x = [] in
if q > p then
for i=0 to rho do
x= q :: x
done;
x;;
this every time I use a cycle "for" ,how can I solve this problem?
There are several problems with your code.
The error is because the for does not return anything, and so the inside of the loop to be purely for side-effect. So it should have unit type. Your use of = does not have unit type, because = is in fact the equality operator, comparing two values, and returning true or false.
So you are using the wrong operator. It appears that you are trying to "assign" to x. But in ML, you cannot assign to "variables", because they are bound to a value when they are defined and cannot change. One way to get mutability, is to use a mutable cell (called a "reference"): you use the ref function to create the mutable cell from an initial value; the ! operator to get its value out; and the := operator to change the value inside.
So for example:
let f q p rho=
let x = ref [] in
if q > p then
for i=0 to rho do
x := q :: !x
done;
!x;;
This kind of loop is probably best expressed using recursion:
let f q p rho=
let rec loop i =
if i > rho then
[]
else
q::(loop (i+1))
in
if q > p then
loop 0
else
[];;
Or we can make it tail recursive:
let f q p rho=
let rec loop i acc =
if i > rho then
acc
else
loop (i+1) (q::acc)
in
if q > p then
loop 0 []
else
[];;
I am trying to do problem 12 in Project Euler.
numDivisor64 is to calculate number of divisors.
I wrote this F# code:
let problem12 =
{1L..300000L} |> Seq.map (fun x->x*(x+1L)/2L) |> Seq.map numDivisor64 |> Seq.filter (fun x->x>500L)
The problem asks to find the number rather than its # of divisors. Besides writing this in a less compact way using loops or recursion, any beautiful method?
Another problem, I occasionally find that I need to convert a 32-bit int version of code to a 64-bit one by adding 'L' to all the numbers. Is there a way to avoid this? Anything like c++ template?
I first wrote
let numDivisor n =
let rec countd n d =
if n%d=0 then
let n2, cnt = countd (n/d) d
n2, cnt+1
else
n, 0
let rec collect n d =
if n < d then 1
elif n%d=0 then
let n2, cnt = countd n d
(cnt+1) * (collect n2 d)
else
collect n (d+1)
collect n 2
Later I found I need bigger integers:
let numDivisor64 n =
let rec countd n d =
if n%d=0L then
let n2, cnt = countd (n/d) d
n2, cnt+1L
else
n, 0L
let rec collect n d =
if n < d then 1L
elif n%d=0L then
let n2, cnt = countd n d
(cnt+1L) * (collect n2 d)
else
collect n (d+1L)
collect n 2L
I would rephrase the search for the first wanted number as follows:
start with an infinite stream of int64's
turn them into triangle numbers
find the first number that satisfies the condition (instead of mapping to the number of divisors, which is not what you want, you want the number itself).
code:
let problem12 =
Seq.initInfinite int64 //the same as Seq.initInfinite (fun n -> int64 n)
|> Seq.map (fun x -> x*(x+1L)/2L)
|> Seq.find (fun x -> numDivisor64 x > 500L)
Regarding the second problem: when I solve project Euler problems I usually use int64's by default, because of type inference restrictions.
It's possible to write a more generic version using the inline keyword. See for instance this thread over at hubFS.
EDIT: here's a more generic version, using the technique described in the above link:
The type signature of NumDivisorG becomes horrible, but should work for any data type that 'knows' *,+,1 and 0.
module NumericLiteralG =
let inline FromZero() = LanguagePrimitives.GenericZero
let inline FromOne() = LanguagePrimitives.GenericOne
let inline numDivisorG n =
let rec countd n d =
if n%d=0G then
let n2, cnt = countd (n/d) d
n2, cnt+1G
else
n, 0G
let rec collect n d =
if n < d then 1G
elif n%d=0G then
let n2, cnt = countd n d
(cnt+1G) * (collect n2 d)
else
collect n (d+1G)
collect n (1G+1G)
let problem12L =
Seq.initInfinite int64 //the same as Seq.initInfinite (fun n -> int64 n)
|> Seq.map (fun x -> x*(x+1L)/2L)
|> Seq.find (fun x -> numDivisorG x > 500L)
let problem12I =
Seq.initInfinite id //the same as Seq.initInfinite (fun n -> n)
|> Seq.map (fun x -> x*(x+1)/2)
|> Seq.find (fun x -> numDivisorG x > 500)
if you have the list of divisors you could write a function to calculate the lowest common multiple of them all (which should be the number in question).
in haskell this looks like
lcmAll = foldl1 lcm
in F# i think it would look like this
let rec lcmAll ( head :: tail ) =
Seq.fold lcm head tail
I'm not sure if F# has a builtin lcm.
The alternative to this is to carry the original number around through all the transformations by using a product type, or tuple.
let problem12 =
{1L..300000L} |> Seq.map (fun x->x*(x+1L)/2L) |> Seq.map (fun x->(x,numDivisor64 x)) |> Seq.filter (fun (x,y)->y>500L)
In regards to the 64 bit number issue, if you give your function an explicit type signature it could force F# to use 64-bit ints (provided the type signature is valid for the function definition). Again this sort of thing works in Haskell, I cannot confirm it does with F#. If you could double check that would be awesome.