Hello I am learning the OCaml language and working on an assignment.
infinite precision natural numbers can be represented as lists of ints between 0 and 9
Write a function that takes an integer and represents it with a list of integers between 0 and 9 where the head
of the list holds the least significant digit and the very last element of the list represents the most significant digit.
If the input is negative return None. We provide you with some use cases:
For example:
toDec 1234 = Some [4; 3; 2; 1]
toDec 0 = Some []
toDec -1234 = None
I have written below code for it.
let rec toDec i =
(
if i < 10 then i::[]
else toDec ((i mod 10)::acc) (i/10) in toDec [] i;
);;
I am getting syntax error on line 4. Since I am new to this language, not able to get what's wrong. Can somebody please help on this.
The in keyword must go with a let. You could use a local function aux, as follows:
let toDec i =
let rec aux acc i =
if i < 10 then i::[]
else aux ((i mod 10)::acc) (i/10)
in
aux [] i
This doesn't do what you want but syntax and types are valid and I'm sure you can fix the rest.
Vicky, you forgot to define acc and also forgot to put else if statement.
Update your code as below,
let rec toDec ?acc:(acc=[]) i =
if i < 0 then None
else if i = 0 then Some acc
else toDec ~acc:((i mod 10)::acc) (i / 10)
Related
New to OCaml and Functional Programming as a whole so I was having some problems with keeping the type ambiguous. I'm trying to make a function which takes in a symbol accum(which looks like (+) or (-.) or (*) etc.) and a function f. My current implementation is below and if let's say I passed in (** f (x) = 3x^2 + 5x + 6 **) but I always get '6' instead of '276' because in the else part I'm not summing adding the results of the previous rounds so I just get the final value of '6'.
I get type errors because of the + so when I throw floats in it breaks. How can I overcome this (let partial accept floats or ints but actually accumulate the answer)?
let rec powerSum(sign )(f):'a =
fun x ->
if x = 0 then
f (x)
else if x < 0 then
raise(Failure "Error arg isn't '+'")
else
powerSum sign f (x-1);
Hint: you should use accum at some point.
This is a homework. OCaml seems to be made by a psychopath.
let prime : int -> bool
= fun n ->
if n > 2 then
let a = n - 1 in
let rec divisor n a =
if a > 1 && n mod a = 0 then false
else if a = 2 && n mod a <> 0 then true
else divisor n a-1 ;;
else if n = 2 then true
else if n = 1 then false
I am not good at coding and I know that my isPrime algorithm is wrong.
But I wonder where in my code is the mistake that produces the syntax error.
Also is there any way to define the isPrime function in a recursive form?
Example:
let rec prime n = ~
You'll get better responses from experts if you don't gratuitously insult their language :-) But I'm an easygoing guy, so I'll take a stab at your syntax error.
There are quite a few problems in this code. Here are 3 that I see right off:
The symbol ;; is used to tell the interpreter that you've entered a full expression that you want it to evaluate. It's definitely out of place in the middle of a function declaration.
Your second let doesn't have an associated in. Every let must have an in after it. The only exception is for defining values at the top level of a module (like your prime function).
The expression divisor n a-1 is parsed as (divisor n a) - 1. You want parentheses like this: divisor a (n - 1).
I have this code in VBA (looping through the array a() of type double):
bm = 0 'tot
b = 0 'prev
For i = 24 To 0 Step -1
BP = b 'prevprev = prev
b = bm 'prev = tot
bm = T * b - BP + a(i) 'tot = a(i) + T * prev - prevprev
Next
p = Exp(-xa * xa) * (bm - BP) / 4 '* (tot - prevprev)/4
I'm putting this in F#. Clearly I could use an array and mutable variables to recreate the VBA. And maybe this is an example of the right time to use mutable that I've seen hinted at. But why not try to do it the most idiomatic way?
I could write a little recursive function to replicate the loop. But it kind of feels like littering to hang out a little sub-loop that has no meaning on its own as a standalone, named function.
I want to do it with List functions. I have a couple ideas, but I'm not there yet. Anyone get this in a snap??
The two vague ideas I have are: 1. I could make two more lists by chopping off one (and two) elements and adding zero-value element(s). And combine those lists. 2. I'm wondering if a list function like map can take trailing terms in the list as arguments. 3. As a general question, I wonder if this might be a case where an experienced person would say that this problem screams for mutable values (and if so does that dampen my enthusiasm for getting on the functional boat).
To give more intuition for the code: The full function that this is excerpted from is a numerical approximation for the cumulative normal distribution. I haven't looked up the math behind this one. "xa" is the absolute value of the main function argument "x" which is the number of standard deviations from zero. Without working through the proof, I don't think there's much more to say than: it's just a formula. (Oh and maybe I should change the variable names--xa and bm etc are pretty wretched. I did put suggestions as comments.)
It's just standard recursion. You make your exit condition and your recur condition.
let rec calc i prevPrev prev total =
if i = 0 then // exit condition; do your final calc
exp(-xa * xa) * (total - prevPrev) / 4.
else // recur condition, call again
let newPrevPrev = prev
let newPrev = total
let newTotal = (T * newPrev - newPrevPrev + a i)
calc (i-1) newPrevPrev newPrev newTotal
calc 24 initPrevPrev initPrev initTotal
or shorter...
let rec calc i prevPrev prev total =
if i = 0 then
exp(-xa * xa) * (total - prevPrev) / 4.
else
calc (i-1) prev total (T * total - prev + a i)
Here's my try at pulling the loop out as a recursive function. I'm not thrilled about the housekeeping to have this stand alone, but I think the syntax is neat. Aside from an error in the last line, that is, where the asterisk in (c * a.Tail.Head) gets the red squiggly for float list not matching type float (but I thought .Head necessarily returned float not list):
let rec RecurseIt (a: float list) c =
match a with
| []-> 0.0
| head::[]-> a.Head
| head::tail::[]-> a.Head + (c * a.Tail) + (RecurseIt a.Tail c)
| head::tail-> a.Head + (c * a.Tail.Head) - a.Tail.Tail.Head + (RecurseIt a.Tail c)
Now I'll try list functions. It seems like I'm going to have to iterate by element rather than finding a one-fell-swoop slick approach.
Also I note in this recursive function that all my recursive calls are in tail position I think--except for the last one which will come one line earlier. I wonder if this creates a stack overflow risk (ie, prevents the compiler from treating the recursion as a loop (if that's the right description), or if I'm still safe because the algo will run as a loop plus just one level of recursion).
EDIT:
Here's how I tried to return a list instead of the sum of the list (so that I could use the 3rd to last element and also sum the elements), but I'm way off with this syntax and still hacking away at it:
let rec RecurseIt (a: float list) c =
match a with
| []-> []
| head::[]-> [a.Head]
| head::tail::[]-> [a.Head + (c * a.Tail)] :: (RecurseIt a.Tail c)
| head::tail-> [a.Head + (c * a.Tail.Head) - a.Tail.Tail.Head] :: (RecurseIt a.Tail c)
Here's my try at a list function. I think the problem felt more complicated than it was due to confusing myself. I just had some nonsense with List.iteri here. Hopefully this is closer to making sense. I hoped some List. function would be neat. Didn't manage. For loop not so idiomatic I think. :
for i in 0 .. a.Length - 1 do
b::
a.Item(i) +
if i > 0 then
T * b.Item(i-1) -
if i > 1 then
b.Item(i-2)
else
0
else
0
So I was doing question 8 on project euler (https://projecteuler.net/problem=8),
and my code was:
def prodcheck (n, count):
digs = []
a = str (n)
for dig in a:
digs.append (int (dig))
n = 0
prod = 1
prodset = []
while n < len (digs):
prod = 1
for num in digs [n: n + count + 1]:
prod *= num
prodset.append (prod)
n += 1
return max(prodset)
and after copying in the huge block number line by line, I got a weird number with a letter as a product(specifically 70573265280L, should have been all numbers), can anyone tell me what went wrong?
letter 'L' at the end of int means long. You should be able to use it normally in other equations as any other number because Python fully supports mixed arithmetic. You can also trim trailing L cause its for informational purpose. So in this case the answer is 70573265280.
For more information about numeric types please visit python documentation page.
I'm very new to OCaml / functional programming, and I'm confused about the implementation of some things that are relatively simple other languages I know. I could use any and all help.
Chiefly: in a program I'm working on, I either increment or decrement a variable based on a certain parameter. Here's something representative of what I have:
let tot = ref 0 in
for i = 0 to s do
if test_num > 0 then
tot := !tot + other_num
else
tot := !tot - other_num
done;;
This is obviously not the way to go about it, because even if the else statement is never taken, the code acts as if it is, each and every time, presumably because it's closer to the bottom of the program? I know OCaml has pretty sophisticated pattern matching, but within this level of coed I need access to a handful of lists I've already created, and, as far as I understand, I can't access those lists from a top-level function without passing them all as parameters.
I know I'm going about this the wrong way, but I have no idea how to do this idiomatically.
Suggestions? Thanks.
edit
Here's a more concise example:
let ex_list = [1; -2; 3; -4] in
let max_mem = ref 0 in
let mem = ref 0 in
let () =
for i = 0 to 3 do
let transition = List.nth ex_list i in
if transition > 0 then (
mem := (!mem + 10);
) else
mem := (!mem - 1);
if (!mem > !max_mem) then (max_mem := !mem);
done;
print_int !max_mem; print_string "\n";
in !mem;
At the end, when I print max_mem, I get 19, though this value should be (0 + 10 - 1 + 10 - 1 = 18). Am I doing the math wrong, or does the problem come from somewhere else?
Your code looks fine to me. It doesn't make a lot of sense as actual code, but I think you're just trying to show a general layout. It's also written in imperative style, which I usually try to avoid if possible.
The if in OCaml acts just like it does in other languages, there's no special thing about being near the bottom of the program. (More precisely, it acts like the ? : ternary operator from C and related languages; i.e., it's an expression.)
Your code doesn't return a useful value; it always returns () (the quintessentially uninteresting value known as "unit").
If we replace your free variables (ones not defined in this bit of code) by constants, and change the code to return a value, we can run it:
# let s = 8 in
let other_num = 7 in
let test_num = 3 in
let tot = ref 0 in
let () =
for i = 0 to s do
if test_num > 0 then
tot := !tot + other_num
else
tot := !tot - other_num
done
in
!tot;;
- : int = 63
#
If you're trying to learn to write in a functional style (i.e., without mutable variables), you would write this loop as a recursive function and make tot a parameter:
# let s = 8 in
let other_num = 7 in
let test_num = 3 in
let rec loop n tot =
if n > s then
tot
else
let tot' =
if test_num > 0 then tot + other_num else tot - other_num
in
loop (n + 1) tot'
in
loop 0 0;;
- : int = 63
It would probably be easier to help if you gave a (edited to add: small :-) self-contained problem that you're trying to solve.
The other parts of your question aren't clear enough to give any advice on. One thing that I might point out is that it's completely idiomatic to use pattern matching when processing lists.
Also, there's nothing wrong with passing things as parameters. That's why the language is called "functional" -- your code consists of functions, which have parameters.
Update
I like to write let () = expr1 in expr2 instead of expr1; expr2. It's just a habit I got into, sorry if it's confusing. The essence is that you're evaluating the first expression just for its side effects (it has type unit), and then returning the value of the second expression.
If you don't have something after the for, the code will evaluate to (), as I said. Since the purpose of the code seems to be to compute the value of !tot, this is what I returned. At the very least, this lets you see the calculated value in the OCaml top level.
tot' is just another variable. If you calculate a new value straightforwardly from a variable named var, it's conventional to name the new value var'. It reads as "var prime".
Update 2
Your example code works OK, but it has the problem that it uses List.nth to traverse a list, which is a slow (quadratic) operation. In fact your code is naturally considered a fold. Here's how you might write it in a functional style:
# let ex_list = [1; -2; 3; -4] in
let process (tot, maxtot) transition =
let tot' = if transition > 0 then tot + 10 else tot - 1 in
(tot', max maxtot tot')
in
List.fold_left process (0, 0) ex_list;;
- : int * int = (18, 19)
#
In addition to Jeffrey's answer, let me second that this is not how you would usually write such code in Ocaml, since it is a very low-level imperative approach. A more functional version would look like this:
let high ex_list =
let deltas = List.map (fun x -> if x > 0 then 10 else -1) ex_list in
snd (List.fold_left (fun (n, hi) d -> (n+d, max (n+d) hi)) (0, 0) deltas)
let test = high [1; -2; 3; -4]