I have a recursive function and I want the rewriting in the Mémoïsant
My recursive function:
let rec sum_cube l =
match l with
| [] -> 0
| x :: s -> (x * x * x) + sum_cube s
and I tried with this:
let memo = Hashtbl.create 17
let rec sum_cub_memo l =
try
Hashtbl.find memo l
with Not_found ->
let fn = function
| [] -> 0
| x::s -> (x * x * x ) sum_cub_memo s
in
Hashtbl.add memo l fn
fn ;;
I have an error:
This expression has type int list -> int but an expression was expected of type int list!!
You should memoize not the function, but the result of the function, e.g., using your definition of sum_cube:
let sum_cube_memo xs =
try Hashtbl.find memo xs with Not_found ->
let res = sum_cube xs in
Hashtbl.add memo xs res;
res
This will work, however there is a caveat. You're using a list of integers as a key. That means, that first the key is transformed to its hash (basically O(n), and will take basically the same amount of time as computing the power of three), second, if there is a hash collision, then every list in the bucket will be compared with the argument list. As a result, your memoized function has the same complexity as your non-memoized function, it has worse performance, and also consumes unbound amount of memory. Is it worthwhile?
sum_cube without memorization.
let sum_cube l =
let cube x =x*x*x in
List.fold_left ( fun acc x -> acc+cube x) 0 l
sum_cube with memorization and trace.
let sum_cube l =
let memo = Hashtbl.create 17 in
let cube_memo x =
try
let xcube= Hashtbl.find memo x in
Printf.printf "find %d -> %d\n" x xcube;
xcube
with Not_found ->
let xcube=x*x*x in
Printf.printf "add %d -> %d\n" x xcube;
Hashtbl.add memo x xcube;
xcube
in
List.fold_left ( fun acc x -> acc+cube_memo x) 0 l
Test :
# sum_cube [4;4;2;3;4;2];;
add 4 -> 64
find 4 -> 64
add 2 -> 8
add 3 -> 27
find 4 -> 64
find 2 -> 8
- : int = 235
Related
When declaring a function, I've 3 different ways:
let f x = ...
let f = (fun x -> ...)
let f = function
| ... -> (pattern matching)
It's this last one that I don't fully understand how it works.
I was doing a function that, considering a list (we'll assume it has integers in it but could be anything), reverses it, pretty basic, but with a complexity of O(n). After struggling for an hour at least I check the answer, and it is written like this:
let reverse lst =
let rec aux acc = function
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst
I thought that using the key word function was just another way of doing patter matching, but when I do this:
let reverse lst =
let rec aux acc =
match aux with
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst
It doesn't work, and idk why. On top of that, why can we add tl at the end of the first function? Isn't aux a single argument function?
There are a few problems with this question. First, the code you give as the solution for reverse is not valid OCaml. It matches aux (which is a function) against list patterns. Most likely aux was supposed to be acc. But even so it doesn't seem right because it should have two arguments (the accumulated result and the input that still needs to be processed).
Second, your two code examples are the same. You seem to be saying that one works and one doesn't work. That doesn't make sense since they're the same.
IMHO you need to rewrite the question if you want to get a helpful answer.
Ocaml uses currying, which means that a two-argument function is the same thing that a function whose return value is a function.
To define a two-argument function, you can combine all the ways you know of creating one-argument functions:
let f x y = x + y
let f x = (fun y -> x + y)
let f x = function
| y -> x + y
let f = (fun x -> (fun y -> x + y))
let f = function
| x -> function
| y -> x + y
let f x = (let g y = x + y in g)
etc, etc.
All these definitions for f lead to the same result:
val f : int -> int -> int = <fun>
# f 3 4;;
- : int = 7
Note that the signature of f is:
val f : int -> int -> int = <fun>
If we added parentheses to better understand this signature, it would be this:
val f : int -> (int -> int) = <fun>
Meaning that f is a one-argument function whose return value is a one-argument function whose return value is an int.
Indeed, if we partially apply f:
# f 3;;
- : int -> int = <fun>
# let add_three = f 3;;
val add_three : int -> int = <fun>
# add_three 4;;
- : int = 7
The code you give at the end of your question is wrong. It's most likely intended to be this:
let reverse lst =
let rec aux acc l =
match l with
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst;;
val reverse : 'a list -> 'a list = <fun>
# reverse [1;2;3;4;5];;
- : int list = [5; 4; 3; 2; 1]
I’m trying to create a function that takes an int list as an argument and returns the sum of the product between an int and its position in the list. To put in an example this : multSum [5; 11; 15] should return (5 * 1 + 11 * 2 + 15 * 3) = 72.
It should be written recursively and I’m trying while avoiding List.map or List.filter or any other prefabricated functions.
By dividing and reigning the query above, I have so far started by trying the following :
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t ;;
val tir : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
then I moved to this :
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto";;
val carto : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
with the final idea to be able to do that :
let prod arg1 arg2 =
tir (+) 1 (carto ( * ) arg1 arg2);;
val prod : int list -> int list -> int = <fun>
But I am stuck now and I’m not sure of my orientation from here forward. I thought of trying to search for the index in a "l" and replace each index int in the acc, in order to make it work but I'm afraid I'm rather complicating things... Any help please ?
Edit 1 :
let rec multSum l =
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t)in
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t in
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto" in
let prod arg1 arg2 =
tir (+) 0 (carto ( * ) arg1 arg2) in
prod l (indices 1 l);;
val multSum : int list -> int = <fun>
Building on your replies, surely these are 'fold' and 'map' rewritten. At least, I'm sure now that I was on the right track. I have come to put together the whole code as signaled above in Edit 1.
It seems to be working well... I know that I want a recursive function and here it is. But, do you think it could be done even shorter recursively of course?
#coredump is quite right about this looking like an ideal scenario for a fold, but the extra functions aren't really that necessary. We can just use a tuple to pass the index and sum information around, then when we're done, discard the index information from the tuple.
let sum_list_prod lst =
let (_, result) = List.fold_left
(fun (i, sum) x -> (i + 1, sum + i * x))
(1, 0)
lst
in
result
Edit: A simple implementation of a left fold to demonstrate the recursion going on here.
let rec foldl f init lst =
match lst with
| [] -> init
| first :: rest -> foldl f (f init first) rest
So working through a simple example with sum_list_prod:
sum_list_prod [2; 3; 4]
Calls the fold like so:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
And as that evaluates:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (2, 2) [3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (3, 8) [4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (4, 20) []
(4, 20)
And then we throw away the 4 because we don't need it anymore and are just left with 20.
Your tir functions looks like a fold; in fact has the exact same type as List.fold_left:
# List.fold_left;;
- : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
In the following snippets the prod function looks like a map2
# List.map2;;
- : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
You can use a fold and a map to compute the function you want, but you also need first to build a list of indices from the list of values. You could do this as follows:
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t);;
For example:
# indices 1 [5;1;3];;
- : int list = [1; 2; 3]
This is not recursive terminal, if you first computed the length of the list, how would you build the list in a recursive terminal way?
Then you should be able to call prod on a list xs and on a secondary list indices 1 xs. It is a bit wasteful because you need to build an auxiliary list, but it looks quite simple to me to understand, higher-order functions like map or fold do work on whole lists so there are fewer corner cases to consider.
But, it might be better to first write a direct recursive function for your particular problem before going the more abstract route.
The direct recursive function also requires no additional memory allocation. If you write a recursive terminal function you'll carry additional accumulator values:
the current position in the list, initially 1
the current sum of products, initially 0
Then, your function has the following skeleton:
let rec f xs index product = match xs with
| [] -> ...
| h::t -> ...
You can wrap it in a main function g:
let g xs = f xs 1 0;;
I have a list of (string * int) list elements and I need to find the biggest int element and return the corresponding(string * int) element.
I have something like this atm, but problem is, I think my approach is more of "typical programming"
let it = [] in
for x = 0 to length LIST - 1 do
let str = ((List.nth LIST x).string) in
let num = ((List.nth LIST x).int) in
let it = it # [num, str] in
let (str, num) = List.hd(List.rev it) in
[str, num]
What I tried to do is to loop through the list and add the string and int value in another list, then sort them, reverse it and then take the head, which should be the max int, then I need to return the pair in (string * int)
Your code is not a well-formed OCaml code. It highlights, however, some number of issues with your understanding of OCaml.
First of all, by default, values in OCaml are immutable. For example,
let x = 0 in
for i = 0 to 10 do
let x = x + 1 in
print_int x;
done
You will get 11111111111 as the output. This is because, during the loop, you are just computing every time the x+1 expression, where x is always 0 and you will always get 1 as the result. This is because, let x = <expr> in <body> is not changing the existing variable x but is creating a new variable x (shadowing any previous definitions) and make it available in the scope of the <body> expression.
Concerning your problem in general, it should be solved as a recursive function greatest_element, which has the following definition,
for an empty list [] it is undefined;
for a list of one element [x] is it is x;
otherwise, for a list of x::xs it is max x (greatest_element xs),
where max x y is x if it is greater or equal to y.
Finally, it looks like you have missed the first steps in OCaml and before solving this task you have to move back and to learn the basics. In particular, you have to learn how to call functions, bind variables, and in general what are the lexical conventions and syntax of the language. If you need pointers, feel free to ask.
First of all, it doesn't seem that you did any kind of sorting in
the code that you provided.
Assuming that your list is of type
(string * int) list then a possible to find the element with the
maximum integer using recursion:
let max_in_list list =
let rec auxiliary max_str max_int = function
| []
-> (max_str, max_int)
| (crt_str, crt_int)::tail when crt_int > max_int
-> auxiliary crt_str crt_int tail
| _::tail
-> auxiliary max_str max_int tail
in
match list with
| []
-> None
| (fst_str, fst_int)::tail
-> Some (auxiliary fst_str fst_int tail)
let check = max_in_list [("some", 1); ("string", 3); ("values", 2)]
You could write a generic maxBy function. This allows you to get the max of any list -
let rec maxBy f = function
| [] -> None
| [ x ] -> Some x
| x :: xs ->
match (maxBy f xs) with
| Some y when (f y) > (f x) -> Some y
| _ -> Some x
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)
let data = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]
(* val data : (string * int) list = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]*)
maxBy (fun (_, num) -> num) data
(* - : (string * int) option = Some ("c", 6) *)
maxBy (fun (str, _) -> str) data
(* - : (string * int) option = Some ("d", 1) *)
maxBy (fun x -> x) [3; 2; 6; 1]
(* - : int option = Some 6 *)
maxBy (fun x -> x) ["c"; "d"; "b"; "a"]
(* - : string option = Some "d" *)
maxBy (fun x -> x) []
(* - : 'a option = None *)
It can be fun to rewrite the same function in various ways. Here's another encoding -
let maxBy f list =
let rec loop r = function
| [] -> r
| x::xs when (f x) > (f r) -> loop x xs
| _::xs -> loop r xs
in
match list with
| [] -> None
| x::xs -> Some (loop x xs)
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)
I just looking for a little advice, how to rewrite code using tail recursion
open Core.Std;;
let rec dig x =
match x with
| 0 -> []
| _ -> x :: dig (x - 1)
;;
let () =
let numbers = dig 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Any advice will be helpful
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (x::s)
f x []
Is this what you want? It's using tail recursion.
Edit:
for a decreasing seq, just replace (x::s) with (List.append s [x]) or (s # [x]) but it's NOT a good idea,and List.rev is better:
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (s # [x])
f x []
let dig x =
let rec f s z =
if z = x then s
else f (z::s) (z+1)
in
f [] 0
not sure if this floats your boat: You may have to tweak the border cases depending if you want 0 or the starting number included.
If you don't want to use List.rev after building the list backwards (which in my opinion is perfectly fine), nor starting your recursion with 0 instead of n, you can use some kind of continuation:
let dig2 x =
let rec aux x kont =
match x with
| 0 -> kont
| _ -> aux (x-1) (fun l -> kont (x::l))
in
aux x (fun l -> l) [];;
Basically each step returns a function that, given the list built by the remaining steps, will append x to it. We start the recursion with the identity function since we don't have anything to build yet. Then, when we exit from the recursion, we thus just have to apply the empty list to the obtained function.
Well, it seems to can have multiple solutions
open Core.Std;;
let rec digtail ?(l=[]) x =
match x with
| 0 -> l
| _ -> digtail ~l: (l # [x]) (x - 1)
;;
let () =
let numbers = digtail 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Thanks to all, you helped a lot.
I want to write a function rotate n l that returns a new list containing the same elements as l, "rotated" n times to the right. For example,
rotate 0 [1;2;3;4] should return [1;2;3;4]
rotate 1 [1;2;3;4] should return [4;1;2;3]
rotate 2 [1;2;3;4] should return [3;4;1;2]
rotate 3 [1;2;3;4] should return [2;3;4;1]
rotate 4 [1;2;3;4] should return [1;2;3;4]
etc.
The behavior of rotate n for n less than 0 should be the same as for n equal to 0.
I want to write this without using the list concatenation operator # from Pervasives.
Update: Here is the rotation function I wrote:
let rot1 l =
let rec iterate acc = function
[] -> []
| [x] -> x :: List.rev acc
| x :: l -> iterate (x :: acc) l
in
iterate [] l;;
But I want it to do the same thing without using List.rev.
Is there a way to do this?
Agree with Jeffrey, show us what you tried. Here's a small hint in case you need to get started. If you can write a function that performs only 1 rotation i.e. equivalent to rotate 1 l. (I call it one_rot). Then rotate can be easily defined as:
let rec rotate n l =
match n with
| 0 -> l
| _ -> rotate (n-1) (one_rot l)
Your solution is perfectly fine for me. Not sure what you have against List.rev but here's a completely stand alone one_rot. Note that we have to sacrifice tail recursion. You could probably make this quite a bit shorter too:
let rec last = function
| [] -> assert false
| [x] -> x
| x::xs -> last xs
let rec init = function
| [] -> []
| [x] -> []
| x::xs -> x::(init xs)
let one_rot l = (last l)::(init l)
This problem can be solved by combining these 3 functions:
cat(skip(list, places), take(list, places))
The implementation looks like:
let rec cat = function
([], y) -> y
| (x::xs, y) -> x :: cat (xs, y)
let rec skip = function
([], _) -> []
| (_::xs as xs1, c) -> if c > 0 then skip(xs, c - 1) else xs1
let rec take = function
([], _) -> []
| (x::xs, c) -> if c > 0 then x :: take(xs, c - 1) else []
let cycle l i =
cat (skip (l, i), take (l, i))
cycle ([1;2;3;4;5;6], 3);;
val it : int list = [4; 5; 6; 1; 2; 3]