PDA

View Full Version : Starting attempts...


scanez
06-21-2002, 07:47 PM
Here we have the simple factorial :)
let rec factorial number =
if number == 0 then
1
else
number * factorial (number-1)

let _ =
if (Array.length Sys.argv) < 2 then begin
Printf.printf "Usage: %s number\n" Sys.argv.(0);
exit 1;
end;

try
let num = int_of_string Sys.argv.(1) in

for i = 0 to num do
Printf.printf "%i! = %i\n" i (factorial i)
done

with Failure "int_of_string" ->
print_endline "You must enter an integer";
exit 1;
GnuVince, if parts look similar to your primes.ml that's because it's what I was looking at when writing it :)

Any suggestions on simple stuff like this that would help me get my feet soaked?

GnuVince
06-21-2002, 08:00 PM
Change

if number == 0 then


to


if number = 0 then


= and == are not the same thing in O'Caml. I think PrBacterio explained it in another thread. You should look for his explanation. Other than that, it's looking great!

By the way, you might want to get this (http://darkhost.mine.nu:81/shl.tgz). It's a tool made by PrBacterio to colorize O'Caml code on VBulletin.

inkedmn
06-21-2002, 08:21 PM
isn't == an equality test and = a definition?

GnuVince
06-21-2002, 08:25 PM
ink: No. In O'Caml, == is physical equality and = is structural equality.

inkedmn
06-21-2002, 08:34 PM
ah, ok...

scanez
06-22-2002, 03:39 AM
Ah sweet, thanks to GnuVince for the correction and link and to PrBacterio for the colorization :)

scanez
06-22-2002, 05:48 PM
Haha! I'm getting there...probably bad style though (is it?), I just basically did line-for-line interpretation of some python code...with some recusrion thrown in :)
(* Calculates the continued fraction representation for the square root
of a positive integer, repeating part is enclosed in parentheses *)

let cont_frac d =
let x = sqrt(float_of_int d) in
let b = int_of_float x in
let y = x -. (float_of_int b) in

Printf.printf "sqrt(%i) = [%i" d b;

(* builds the continued fraction recursively *)
let rec build_cont_frac x b =
if x < 0.00001 then () (* too small to continue *)
else begin
let y = 1.0 /. x in
let a = int_of_float y in

if a = 2*b then
Printf.printf "%i)" a
else begin
Printf.printf "%i, " a;
build_cont_frac (y -. float_of_int a) b;
end;
end
in

if y > 0.00001 then begin
Printf.printf ", (";
build_cont_frac y b;
end;

Printf.printf "]\n";
;;

let _ =
if (Array.length Sys.argv) < 2 then begin
Printf.printf "Usage: %s integer\n" Sys.argv.(0);
exit 1;
end;

try
cont_frac (int_of_string Sys.argv.(1));

with Failure "int_of_string" ->
print_endline "You must enter an integer";
exit 1;

scanez
06-22-2002, 07:11 PM
Any real number x can be represented in the form

x = a0 + b1/(a1 + b2/(a2 + b3/(...))

all that messy stuff after the a0 is just a fraction, under a fraction, under a fraction, etc... A simple continued fraction is one where the b's are all 1. So for example,

http://www.u.arizona.edu/~scanez/img1.png

is the continued fraction for 54/23. We use shorthand notation

54/23 = [2; 2, 1, 7]

The square root of any square-free positive integer has the form

sqrt(d) = [a0; (a1, a2, ..... , a2, a1, 2*a0)]

with the part in parentheses repeating forever (Amazing result eh?) For example

sqrt(118 ) = [10, (1, 6, 3, 2, 10, 2, 3, 6, 1, 20)]

and there are many other such patterns as well in the study of continued fractions (which I spent my first summer of college researching :)) Hopefully the functionality of my program makes a little more sense now, it's not perfect, but works for most small (<1000) integers.

scanez
06-25-2002, 04:54 AM
Adaption of factorial using List stuff :) (without checking for number of args, arg types)
let mul a b = a * b;;

let rec build_list i = match i with
| 0 -> []
| m -> List.rev_append [m] (build_list (i-1))

let _ =
let l = build_list (int_of_string Sys.argv.(1)) in
let ans = List.fold_left mul 1 l in

Printf.printf "%i\n" ans;
Looking good?

GnuVince
06-25-2002, 01:16 PM
Your build_list function could be written this way (cleaner):


let rec build_list i = match i with
0 -> []
| n -> n::(build_list (i-1));;


Or if you want to be more terse (something I like :))


let rec build_list2 = function
0 -> []
| n -> n::(build_list2 (n-1));;


This second example produces exactly the same code, but it's a "special" function. Since there are many functions in O'Caml that just do pattern-matching, there's a special construct. It implicitly assumes an argument (which is why I don't have the i argument). Use it if you like. Jemfinch doesn't like it. I personnaly think it's cute.

jemfinch
06-25-2002, 05:16 PM
It's a fine function, scanez, as long as you understand it's inefficient, and not the most efficient way to implement a factorial.

This is probably a bit more efficient:


let rec factorial_aux n acc =
if n = 0 then acc else factorial_aux (n*acc) (pred acc)

let factorial n =
if n >= 0 then factorial_aux n 1 else raise (Failure "factorial requires an integer greater than zero.")


Pardon my syntax if it's wrong.

Jeremy

GnuVince
06-25-2002, 05:28 PM
Jeremy: I think he was trying to get a grasp of lists.

jemfinch
06-25-2002, 05:39 PM
I just wanted to make sure :) Every list element consumes three machine words, so I wanted to make sure he wasn't trying to do it for efficiency's sake.

Jeremy

GnuVince
06-25-2002, 05:40 PM
Well, scanez is VERY much into maths, so I guess if I had to ask someone about the factorial algorithm, I would ask him :)

scanez
06-25-2002, 09:03 PM
Hehe, yeah, I was just trying to play and become more familiar with lists :) I'd never to do it that way in a real application, but thanks anyway. It's nice to know there are people here watching your back :D

Jemfinch, GnuVince: I read about the function keyword in one of the other threads, is there any REAL benefit to using it? Also, is matching preferred over if...then? For example, which of these would be preferred
let some_function n =
if n = 0 then something
else something_else
or
let some_function n = match n with
0 -> something
| _ -> something_else
Or is just a matter of personal taste?

GnuVince
06-25-2002, 09:10 PM
About the function keyword, there's no difference whatsoever. with using match x with.

about if vs. match, I don't know. But I guess when you got more than 3 possibilities, it's a good idea to use match. Personally, I quite like using pattern matching since I find it easier to read.

jemfinch
06-25-2002, 11:04 PM
Originally posted by scanez
Jemfinch, GnuVince: I read about the function keyword in one of the other threads, is there any REAL benefit to using it?


No, there aren't. There are, in fact, some major disadvantages to using it:

People reading your code don't get to see the name of your argument, which in a type inferred language is often the only reference they have to the type of the argument.
You can only construct a function with one (unnamed) argument. If you later need to extend your program by adding a second argument, it'll be more work (a lot of that work involving re-indenting the entire function appropriately)
It's just more variability in your code. You'll be using match statements anyway; there's no reason to use function and match when you can just use match, IMO.


I gave an explanation in my thread about O'Caml Style, too.


Also, is matching preferred over if...then?


When it's a binary choice (either one or the other), an if statement is preferred. When it's either necessary to deconstruct a constructor, or when you have several possiblities, a match statement is probably preferred. If you have to use guards in your match statement, it's likely that an if statement is preferred.


For example, which of these would be preferred
let some_function n =
if n = 0 then something
else something_else
or
let some_function n = match n with
0 -> something
| _ -> something_else


The first one. You'll also note that in the case of a factorial, the if statement is more robust against error: I can check that the argument is <= to 0, which doesn't cause infinite recursion on negative input.


Or is just a matter of personal taste?[/B]

It might be, but then, all personal taste decomposes into "Good Taste" and "Bad Taste" :smoke:

Jeremy